1 Commits

Author SHA1 Message Date
9830cbee71 archrunner db query searches for symbol, name 2024-03-15 10:03:35 +01:00
10 changed files with 120 additions and 229 deletions

View File

@ -524,7 +524,7 @@ class Backtester:
if actual_minus_reserved <= 0:
cena = price if price else self.get_last_price(time, self.symbol)
if (self.cash - reserved_price - float(int(size)*float(cena))) < 0:
printanyway("ERROR: not enough cash for shorting. cash",self.cash,"reserved",reserved,"available",self.cash-reserved,"needed",float(int(size)*float(cena)))
printanyway("not enough cash for shorting. cash",self.cash,"reserved",reserved,"available",self.cash-reserved,"needed",float(int(size)*float(cena)))
return -1
#check for available cash
@ -550,7 +550,7 @@ class Backtester:
if actual_plus_reserved_qty >= 0:
cena = price if price else self.get_last_price(time, self.symbol)
if (self.cash - reserved_price - float(int(size)*float(cena))) < 0:
printanyway("ERROR: not enough cash to buy long. cash",self.cash,"reserved_qty",reserved_qty,"reserved_price",reserved_price, "available",self.cash-reserved_price,"needed",float(int(size)*float(cena)))
printanyway("not enough cash to buy long. cash",self.cash,"reserved_qty",reserved_qty,"reserved_price",reserved_price, "available",self.cash-reserved_price,"needed",float(int(size)*float(cena)))
return -1
id = str(uuid4())

View File

@ -667,14 +667,14 @@
</div>
<div class="form-group mt-3">
<label for="logHere" class="form-label">Log</label>
<div id="log-container"style="height:700px;border:1px solid black;">
<!-- <pre id="log-content"></pre> -->
<div id="log-container">
<pre id="log-content"></pre>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="logRefreshButton" value="Refresh">Refresh</button>
<button type="button" class="btn btn-secondary" id="closeLogModal" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
@ -1166,9 +1166,9 @@
<!-- <script src="/static/js/archivetables.js?v=1.05"></script> -->
<!-- archiveTables split into separate files -->
<script src="/static/js/tables/archivetable/init.js?v=1.12"></script>
<script src="/static/js/tables/archivetable/functions.js?v=1.11"></script>
<script src="/static/js/tables/archivetable/functions.js?v=1.10"></script>
<script src="/static/js/tables/archivetable/modals.js?v=1.07"></script>
<script src="/static/js/tables/archivetable/handlers.js?v=1.11"></script>
<script src="/static/js/tables/archivetable/handlers.js?v=1.09"></script>
<!-- Runmanager functionality -->
<script src="/static/js/tables/runmanager/init.js?v=1.1"></script>
@ -1178,7 +1178,7 @@
<script src="/static/js/livewebsocket.js?v=1.02"></script>
<script src="/static/js/realtimechart.js?v=1.02"></script>
<script src="/static/js/mytables.js?v=1.03"></script>
<script src="/static/js/mytables.js?v=1.02"></script>
<script src="/static/js/testlist.js?v=1.01"></script>
<script src="/static/js/ml.js?v=1.02"></script>
<script src="/static/js/common.js?v=1.01"></script>

View File

@ -90,55 +90,9 @@ $(document).ready(function () {
monaco.languages.register({ id: 'python' });
monaco.languages.register({ id: 'json' });
//Register mylogs language
monaco.languages.register({ id: 'mylogs' });
// Register the TOML language
monaco.languages.setLanguageConfiguration('mylogs', {
comments: {
lineComment: '//', // Adjust if your logs use a different comment symbol
},
brackets: [['[', ']'], ['{', '}']], // Array and object brackets
autoClosingPairs: [
{ open: '{', close: '}', notIn: ['string'] },
{ open: '"', close: '"', notIn: ['string', 'comment'] },
{ open: "'", close: "'", notIn: ['string', 'comment'] },
],
});
monaco.languages.setMonarchTokensProvider('mylogs', {
tokenizer: {
root: [
[/#.*/, 'comment'], // Comments (if applicable)
// Timestamps
[/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+/, 'timestamp'],
// Log Levels
[/\b(INFO|DEBUG|WARNING|ERROR|CRITICAL)\b/, 'log-level'],
// Strings
[/".*"/, 'string'],
[/'.*'/, 'string'],
// Key-Value Pairs
[/[A-Za-z_]+\s*:/, 'key'],
[/-?\d+\.\d+/, 'number.float'], // Floating-point
[/-?\d+/, 'number.integer'], // Integers
[/\btrue\b/, 'boolean.true'],
[/\bfalse\b/, 'boolean.false'],
// Other Words and Symbols
[/[A-Za-z_]+/, 'identifier'],
[/[ \t\r\n]+/, 'white'],
[/[\[\]{}(),]/, 'delimiter'], // Expand if more delimiters exist
]
}
});
monaco.languages.register({ id: 'toml' });
// Define the TOML language configuration
monaco.languages.setLanguageConfiguration('toml', {
comments: {

View File

@ -6,7 +6,6 @@ let editor_diff_arch1
let editor_diff_arch2
var archData = null
var batchHeaders = []
var editorLog = null
function refresh_arch_and_callback(row, callback) {
//console.log("entering refresh")
@ -473,34 +472,13 @@ function refresh_logfile() {
contentType: "application/json",
dataType: "json",
success:function(response){
if (editorLog) {
editorLog.dispose();
}
if (response.lines.length == 0) {
value = "no records";
// $('#log-content').html("no records");
$('#log-content').html("no records");
}
else {
//console.log(response.lines)
//var escapedLines = response.lines.map(line => escapeHtml(line));
value = response.lines.join('\n')
// $('#log-content').html(escapedLines.join('\n'));
}
require(["vs/editor/editor.main"], () => {
editorLog = monaco.editor.create(document.getElementById('log-container'), {
value: value,
language: 'mylogs',
theme: 'tomlTheme-dark',
automaticLayout: true,
readOnly: true
});
});
// Focus at the end of the file:
const model = editorLog.getModel();
const lastLineNumber = model.getLineCount();
const lastLineColumn = model.getLineMaxColumn(lastLineNumber);
editorLog.setPosition({ lineNumber: lastLineNumber, column: lastLineColumn });
editorLog.revealPosition({ lineNumber: lastLineNumber, column: lastLineColumn });
var escapedLines = response.lines.map(line => escapeHtml(line));
$('#log-content').html(escapedLines.join('\n'));
}
},
error: function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");

View File

@ -265,8 +265,8 @@ $(document).ready(function () {
$('#diff_first').text(record1.name);
$('#diff_second').text(record2.name);
$('#diff_first_id').text(data1.id + ' Batch: ' + data1.batch_id);
$('#diff_second_id').text(data2.id + ' Batch: ' + data2.batch_id);
$('#diff_first_id').text(data1.id);
$('#diff_second_id').text(data2.id);
//monaco
require(["vs/editor/editor.main"], () => {
@ -358,13 +358,8 @@ $(document).ready(function () {
})
});
$('#closeLogModal').click(function () {
editorLog.dispose()
});
//button to query log
$('#logRefreshButton').click(function () {
editorLog.dispose()
refresh_logfile()
});

View File

@ -35,62 +35,40 @@ class StrategyClassicSL(Strategy):
max_sum_profit_to_quit_rel = safe_get(self.state.vars, "max_sum_profit_to_quit_rel", None)
max_sum_loss_to_quit_rel = safe_get(self.state.vars, "max_sum_loss_to_quit_rel", None)
#load typ direktivy hard/soft cutoff
hard_cutoff = safe_get(self.state.vars, "hard_cutoff", False)
rel_profit = round(float(np.sum(self.state.rel_profit_cum)),5)
if max_sum_profit_to_quit_rel is not None:
if rel_profit >= float(max_sum_profit_to_quit_rel):
msg = f"QUITTING {hard_cutoff=} MAX SUM REL PROFIT REACHED {max_sum_profit_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
printanyway(msg)
self.state.ilog(e=msg)
self.state.ilog(e=f"QUITTING MAX SUM REL PROFIT REACHED {max_sum_profit_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.state.vars.pending = "max_sum_profit_to_quit_rel"
if self.mode not in [Mode.BT, Mode.PREP]:
send_to_telegram(msg)
if hard_cutoff:
self.hard_stop = True
else:
self.soft_stop = True
send_to_telegram(f"QUITTING MAX SUM REL PROFIT REACHED {max_sum_profit_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.signal_stop = True
return True
if max_sum_loss_to_quit_rel is not None:
if rel_profit < 0 and rel_profit <= float(max_sum_loss_to_quit_rel):
msg=f"QUITTING {hard_cutoff=} MAX SUM REL LOSS REACHED {max_sum_loss_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
printanyway(msg)
self.state.ilog(e=msg)
self.state.ilog(e=f"QUITTING MAX SUM REL LOSS REACHED {max_sum_loss_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.state.vars.pending = "max_sum_loss_to_quit_rel"
if self.mode not in [Mode.BT, Mode.PREP]:
send_to_telegram(msg)
if hard_cutoff:
self.hard_stop = True
else:
self.soft_stop = True
send_to_telegram(f"QUITTING MAX SUM REL LOSS REACHED {max_sum_loss_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.signal_stop = True
return True
if max_sum_profit_to_quit is not None:
if float(self.state.profit) >= float(max_sum_profit_to_quit):
msg = f"QUITTING {hard_cutoff=} MAX SUM ABS PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
printanyway(msg)
self.state.ilog(e=msg)
self.state.ilog(e=f"QUITTING MAX SUM ABS PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.state.vars.pending = "max_sum_profit_to_quit"
if self.mode not in [Mode.BT, Mode.PREP]:
send_to_telegram(msg)
if hard_cutoff:
self.hard_stop = True
else:
self.soft_stop = True
send_to_telegram(f"QUITTING MAX SUM ABS PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.signal_stop = True
return True
if max_sum_loss_to_quit is not None:
if float(self.state.profit) < 0 and float(self.state.profit) <= float(max_sum_loss_to_quit):
msg = f"QUITTING {hard_cutoff=} MAX SUM ABS LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}"
printanyway(msg)
self.state.ilog(e=msg)
self.state.ilog(e=f"QUITTING MAX SUM ABS LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.state.vars.pending = "max_sum_loss_to_quit"
if self.mode not in [Mode.BT, Mode.PREP]:
send_to_telegram(msg)
if hard_cutoff:
self.hard_stop = True
else:
self.soft_stop = True
send_to_telegram(f"QUITTING MAX SUM ABS LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}")
self.signal_stop = True
return True
return False
@ -436,7 +414,7 @@ class StrategyClassicSL(Strategy):
populate_all_indicators(item, self.state)
#pro přípravu dat next nevoláme
if self.mode == Mode.PREP or self.soft_stop:
if self.mode == Mode.PREP:
return
else:
self.next(item, self.state)

View File

@ -80,8 +80,7 @@ class Strategy:
self.pe = pe
self.se = se
#signal stop - internal
self.hard_stop = False #indikuje hard stop, tedy vypnuti strategie
self.soft_stop = False #indikuje soft stop (napr. při dosažení max zisku/ztráty), tedy pokracovani strategie, vytvareni dat, jen bez obchodu
self.signal_stop = False
#prdelat queue na dynamic - podle toho jak bud uchtit pracovat s multiresolutions
#zatim jen jedna q1
@ -434,7 +433,7 @@ class Strategy:
#printnow(current_thread().name, "Items waiting in queue:", self.q1.qsize())
except queue.Empty:
#check internal signals - for profit/loss optim etc - valid for runner
if self.hard_stop:
if self.signal_stop:
print(current_thread().name, "Stopping signal - internal")
break
@ -455,7 +454,7 @@ class Strategy:
if item == "last" or self.se.is_set():
print(current_thread().name, "stopping")
break
elif self.hard_stop:
elif self.signal_stop:
print(current_thread().name, "Stopping signal - internal")
break
elif self.pe.is_set():

View File

@ -5,108 +5,99 @@ from v2realbot.utils.utils import slice_dict_lists,zoneUTC,safe_get, AttributeDi
#id = "b11c66d9-a9b6-475a-9ac1-28b11e1b4edf"
#state = AttributeDict(vars={})
from rich import print
from traceback import format_exc
def attach_previous_data(state):
"""""
Attaches data from previous runner of the same batch.
"""""
print("ATTACHING PREVIOUS DATA")
try:
runner : Runner
#get batch_id of current runer
res, runner = cs.get_runner(state.runner_id)
if res < 0:
if runner.batch_id is None:
print(f"No batch_id found for runner {runner.id}")
else:
print(f"Couldnt get previous runner {state.runner_id} error: {runner}")
return None
batch_id = runner.batch_id
#batch_id = "6a6b0bcf"
res, runner_ids =cs.get_archived_runnerslist_byBatchID(batch_id, "desc")
if res < 0:
msg = f"error whne fetching runners of batch {batch_id} {runner_ids}"
print(msg)
return None
if runner_ids is None or len(runner_ids) == 0:
print(f"NO runners found for batch {batch_id} {runner_ids}")
return None
last_runner = runner_ids[0]
print("Previous runner identified:", last_runner)
#get archived header - to get transferables
runner_header : RunArchive = None
res, runner_header = cs.get_archived_runner_header_byID(last_runner)
if res < 0:
print(f"Error when fetching runner header {last_runner}")
return None
state.vars["transferables"] = runner_header.transferables
print("INITIALIZED transferables", state.vars["transferables"])
#get details from the runner
print(f"Fetching runner details of {last_runner}")
res, val = cs.get_archived_runner_details_byID(last_runner)
if res < 0:
print(f"no archived runner {last_runner}")
return None
detail = RunArchiveDetail(**val)
#print("toto jsme si dotahnuli", detail.bars)
if len(detail.bars["time"]) == 0:
print(f"no bars for runner {last_runner}")
return None
# from stratvars directives
attach_previous_bar_data = safe_get(state.vars, "attach_previous_bar_data", 50)
attach_previous_tick_data = safe_get(state.vars, "attach_previous_tick_data", None)
#indicators datetime utc
indicators = slice_dict_lists(d=detail.indicators[0],last_item=attach_previous_bar_data, time_to_datetime=True)
#time -datetime utc, updated - timestamp float
bars = slice_dict_lists(d=detail.bars, last_item=attach_previous_bar_data, time_to_datetime=True)
cbar_ids = {}
#zarovname tick spolu s bar daty
if attach_previous_tick_data is None:
oldest_timestamp = bars["updated"][0]
#returns only values older that oldest_timestamp
cbar_inds = filter_timeseries_by_timestamp(detail.indicators[1], oldest_timestamp)
runner : Runner
#get batch_id of current runer
res, runner = cs.get_runner(state.runner_id)
if res < 0:
if runner.batch_id is None:
print(f"No batch_id found for runner {runner.id}")
else:
cbar_inds = slice_dict_lists(d=detail.indicators[1],last_item=attach_previous_tick_data)
#USE these as INITs - TADY SI TO JESTE ZASTAVIT a POROVNAT
#print("state.indicatorsL", state.indicators, "NEW:", indicators)
state.indicators = AttributeDict(**indicators)
print("transfered indicators:", len(state.indicators["time"]))
#print("state.bars", state.bars, "NEW:", bars)
state.bars = AttributeDict(bars)
print("transfered bars:", len(state.bars["time"]))
#print("state.cbar_indicators", state.cbar_indicators, "NEW:", cbar_inds)
state.cbar_indicators = AttributeDict(cbar_inds)
print("transfered ticks:", len(state.cbar_indicators["time"]))
print("TRANSFERABLEs INITIALIZED")
#bars
#transferable_state_vars = ["martingale", "batch_profit"]
#1. pri initu se tyto klice v state vars se namapuji do ext_data ext_data["transferrables"]["martingale"] = state.vars["martingale"]
#2. pri transferu se vse z ext_data["trasferrables"] dá do stejnénné state.vars["martingale"]
#3. na konci dne se uloží do sloupce transferables v RunArchive
#pridavame dailyBars z extData
# if hasattr(detail, "ext_data") and "dailyBars" in detail.ext_data:
# state.dailyBars = detail.ext_data["dailyBars"]
return
except Exception as e:
print(str(e)+format_exc())
print(f"Couldnt get previous runner {state.runner_id} error: {runner}")
return None
batch_id = runner.batch_id
#batch_id = "6a6b0bcf"
res, runner_ids =cs.get_archived_runnerslist_byBatchID(batch_id, "desc")
if res < 0:
msg = f"error whne fetching runners of batch {batch_id} {runner_ids}"
print(msg)
return None
if runner_ids is None or len(runner_ids) == 0:
print(f"NO runners found for batch {batch_id} {runner_ids}")
return None
last_runner = runner_ids[0]
print("Previous runner identified:", last_runner)
#get archived header - to get transferables
runner_header : RunArchive = None
res, runner_header = cs.get_archived_runner_header_byID(last_runner)
if res < 0:
print(f"Error when fetching runner header {last_runner}")
return None
state.vars["transferables"] = runner_header.transferables
print("INITIALIZED transferables", state.vars["transferables"])
#get details from the runner
print(f"Fetching runner details of {last_runner}")
res, val = cs.get_archived_runner_details_byID(last_runner)
if res < 0:
print(f"no archived runner {last_runner}")
return None
detail = RunArchiveDetail(**val)
#print("toto jsme si dotahnuli", detail.bars)
# from stratvars directives
attach_previous_bar_data = safe_get(state.vars, "attach_previous_bar_data", 50)
attach_previous_tick_data = safe_get(state.vars, "attach_previous_tick_data", None)
#indicators datetime utc
indicators = slice_dict_lists(d=detail.indicators[0],last_item=attach_previous_bar_data, time_to_datetime=True)
#time -datetime utc, updated - timestamp float
bars = slice_dict_lists(d=detail.bars, last_item=attach_previous_bar_data, time_to_datetime=True)
#zarovname tick spolu s bar daty
if attach_previous_tick_data is None:
oldest_timestamp = bars["updated"][0]
#returns only values older that oldest_timestamp
cbar_inds = filter_timeseries_by_timestamp(detail.indicators[1], oldest_timestamp)
else:
cbar_inds = slice_dict_lists(d=detail.indicators[1],last_item=attach_previous_tick_data)
#USE these as INITs - TADY SI TO JESTE ZASTAVIT a POROVNAT
#print("state.indicatorsL", state.indicators, "NEW:", indicators)
state.indicators = AttributeDict(**indicators)
print("transfered indicators:", len(state.indicators["time"]))
#print("state.bars", state.bars, "NEW:", bars)
state.bars = AttributeDict(bars)
print("transfered bars:", len(state.bars["time"]))
#print("state.cbar_indicators", state.cbar_indicators, "NEW:", cbar_inds)
state.cbar_indicators = AttributeDict(cbar_inds)
print("transfered ticks:", len(state.cbar_indicators["time"]))
print("TRANSFERABLEs INITIALIZED")
#bars
#transferable_state_vars = ["martingale", "batch_profit"]
#1. pri initu se tyto klice v state vars se namapuji do ext_data ext_data["transferrables"]["martingale"] = state.vars["martingale"]
#2. pri transferu se vse z ext_data["trasferrables"] dá do stejnénné state.vars["martingale"]
#3. na konci dne se uloží do sloupce transferables v RunArchive
#pridavame dailyBars z extData
# if hasattr(detail, "ext_data") and "dailyBars" in detail.ext_data:
# state.dailyBars = detail.ext_data["dailyBars"]
return
# if __name__ == "__main__":
# attach_previous_data(state)

View File

@ -78,7 +78,7 @@ def execute_signal_generator(state, data, name):
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
status=TradeStatus.READY,
generated_by=name,
size=int(multiplier*state.vars.chunk),
size=multiplier*state.vars.chunk,
size_multiplier = multiplier,
direction=TradeDirection.LONG,
entry_price=None,
@ -90,7 +90,7 @@ def execute_signal_generator(state, data, name):
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
status=TradeStatus.READY,
generated_by=name,
size=int(multiplier*state.vars.chunk),
size=multiplier*state.vars.chunk,
size_multiplier = multiplier,
direction=TradeDirection.SHORT,
entry_price=None,

View File

@ -151,17 +151,13 @@ def get_multiplier(state: StrategyState, data, signaloptions: dict, direction: T
#pocet ztrátových obchodů v řadě mi udává multiplikátor (0 - 1, 1 ztráta 2x, 3 v řadě - 4x atp.)
if martingale_enabled:
#martingale base - základ umocňování - klasicky 2
base = float(utls.safe_get(options, "martingale_base", 2))
#pocet aktuálních konsekutivních ztrát
cont_loss_series_cnt = state.vars["transferables"]["martingale"]["cont_loss_series_cnt"]
if cont_loss_series_cnt == 0:
multiplier = 1
else:
multiplier = base ** cont_loss_series_cnt
multiplier = 2 ** cont_loss_series_cnt
state.ilog(lvl=1,e=f"SIZER - MARTINGALE {multiplier}", options=options, time=state.time, cont_loss_series_cnt=cont_loss_series_cnt)
if (martingale_enabled is False and multiplier > 1) or multiplier <= 0:
state.ilog(lvl=1,e=f"SIZER - Mame nekde problem MULTIPLIER mimo RANGE ERROR {multiplier}", options=options, time=state.time)
multiplier = 1