diff --git a/testy/getrunnerdetail.py b/testy/getrunnerdetail.py new file mode 100644 index 0000000..e7e9945 --- /dev/null +++ b/testy/getrunnerdetail.py @@ -0,0 +1,89 @@ + +from v2realbot.common.model import RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveViewPagination, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem, InstantIndicator, DataTablesRequest +import v2realbot.controller.services as cs +from v2realbot.utils.utils import slice_dict_lists,zoneUTC,safe_get, AttributeDict +id = "b11c66d9-a9b6-475a-9ac1-28b11e1b4edf" +state = AttributeDict(vars={}) + +##základ pro init_attached_data in strategy.init + +# def get_previous_runner(state): +# runner : Runner +# res, runner = cs.get_runner(state.runner_id) +# if res < 0: +# print(f"Not running {id}") +# return 0, None + +# return 0, runner.batch_id + +def attach_previous_data(state): + runner : Runner + #get batch_id of current runer + res, runner = cs.get_runner(state.runner_id) + if res < 0 or runner.batch_id is None: + print(f"Couldnt get previous runner {val}") + 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 details from the runner + res, val = cs.get_archived_runner_details_byID(last_runner) + if res < 0: + print(f"no archived runner {last_runner}") + + detail = RunArchiveDetail(**val) + #print("toto jsme si dotahnuli", detail.bars) + + # from stratvars directives + attach_previous_bars_indicators = safe_get(state.vars, "attach_previous_bars_indicators", 50) + attach_previous_cbar_indicators = safe_get(state.vars, "attach_previous_cbar_indicators", 50) + # [stratvars] + # attach_previous_bars_indicators = 50 + # attach_previous_cbar_indicators = 50 + + #indicators datetime utc + indicators = slice_dict_lists(d=detail.indicators[0],last_item=attach_previous_bars_indicators, time_to_datetime=True) + + #time -datetime utc, updated - timestamp float + bars = slice_dict_lists(d=detail.bars, last_item=attach_previous_bars_indicators, time_to_datetime=True) + + #cbar_indicatzors #float + cbar_inds = slice_dict_lists(d=detail.indicators[1],last_item=attach_previous_cbar_indicators) + + #USE these as INITs - TADY SI TO JESTE ZASTAVIT a POROVNAT + print(f"{state.indicators=} NEW:{indicators=}") + state.indicators = indicators + print(f"{state.bars=} NEW:{bars=}") + state.bars = bars + print(f"{state.cbar_indicators=} NEW:{cbar_inds=}") + state.cbar_indicators = cbar_inds + + print("BARS and INDS INITIALIZED") + #bars + + + #tady budou pripadne dalsi inicializace, z ext_data + print("EXT_DATA", detail.ext_data) + #podle urciteho nastaveni napr.v konfiguraci se pouziji urcite promenne + + #pridavame dailyBars z extData + # if hasattr(detail, "ext_data") and "dailyBars" in detail.ext_data: + # state.dailyBars = detail.ext_data["dailyBars"] + + +if __name__ == "__main__": + attach_previous_data(state) \ No newline at end of file diff --git a/v2realbot/ENTRY_ClassicSL_v01.py b/v2realbot/ENTRY_ClassicSL_v01.py index 349e549..3667906 100644 --- a/v2realbot/ENTRY_ClassicSL_v01.py +++ b/v2realbot/ENTRY_ClassicSL_v01.py @@ -16,6 +16,7 @@ from v2realbot.strategyblocks.newtrade.signals import signal_search from v2realbot.strategyblocks.activetrade.activetrade_hub import manage_active_trade from v2realbot.strategyblocks.inits.init_indicators import initialize_dynamic_indicators from v2realbot.strategyblocks.inits.init_directives import intialize_directive_conditions +from v2realbot.strategyblocks.inits.init_attached_data import attach_previous_data from alpaca.trading.client import TradingClient from v2realbot.config import ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, DATA_DIR from alpaca.trading.models import Calendar @@ -116,7 +117,8 @@ def init(state: StrategyState): state.vars.loaded_models = {} #state attributes for martingale sizing mngmt - state.vars["martingale"] = dict(cont_loss_series_cnt=0) + state.vars["transferables"] = {} + state.vars["transferables"]["martingale"] = dict(cont_loss_series_cnt=0) #INITIALIZE CBAR INDICATORS - do vlastni funkce #state.cbar_indicators['ivwap'] = [] @@ -131,6 +133,9 @@ def init(state: StrategyState): initialize_dynamic_indicators(state) intialize_directive_conditions(state) + #attach part of yesterdays data, bars, indicators, cbar_indicators + attach_previous_data(state) + #intitialize indicator mapping (for use in operation) - mozna presunout do samostatne funkce prip dat do base kdyz se osvedci local_dict_cbar_inds = {key: state.cbar_indicators[key] for key in state.cbar_indicators.keys() if key != "time"} local_dict_inds = {key: state.indicators[key] for key in state.indicators.keys() if key != "time"} diff --git a/v2realbot/common/model.py b/v2realbot/common/model.py index 78f4f17..8674b30 100644 --- a/v2realbot/common/model.py +++ b/v2realbot/common/model.py @@ -301,8 +301,7 @@ class RunArchive(BaseModel): bt_from: Optional[datetime] = None bt_to: Optional[datetime] = None strat_json: Optional[str] = None - ##bude decomiss, misto toho stratvars_toml - stratvars: Optional[dict] = None + transferables: Optional[dict] = None #varaibles that are transferrable to next run settings: Optional[dict] = None ilog_save: Optional[bool] = False profit: float = 0 diff --git a/v2realbot/common/transform.py b/v2realbot/common/transform.py index a44d8c4..53ad582 100644 --- a/v2realbot/common/transform.py +++ b/v2realbot/common/transform.py @@ -83,5 +83,6 @@ def row_to_runarchive(row: dict) -> RunArchive: end_positions=int(row['end_positions']), end_positions_avgp=float(row['end_positions_avgp']), metrics=orjson.loads(row['metrics']), - stratvars_toml=row['stratvars_toml'] + stratvars_toml=row['stratvars_toml'], + transferables=orjson.loads(row['transferables']) if row['transferables'] else None ) \ No newline at end of file diff --git a/v2realbot/controller/configs.py b/v2realbot/controller/configs.py index f064d12..1b2bc0c 100644 --- a/v2realbot/controller/configs.py +++ b/v2realbot/controller/configs.py @@ -1,7 +1,6 @@ import v2realbot.common.db as db -from v2realbot.common.model import RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveViewPagination, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem, InstantIndicator, DataTablesRequest -import orjson +from v2realbot.common.model import ConfigItem import v2realbot.utils.config_handler as ch # region CONFIG db services diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py index 75af547..0f3782a 100644 --- a/v2realbot/controller/services.py +++ b/v2realbot/controller/services.py @@ -35,6 +35,7 @@ from sqlite3 import OperationalError, Row import v2realbot.strategyblocks.indicators.custom as ci from v2realbot.strategyblocks.inits.init_indicators import initialize_dynamic_indicators from v2realbot.strategyblocks.indicators.indicators_hub import populate_dynamic_indicators +from v2realbot.strategyblocks.inits.init_attached_data import attach_previous_data from v2realbot.interfaces.backtest_interface import BacktestInterface import os import v2realbot.reporting.metricstoolsimage as mt @@ -412,7 +413,7 @@ def run_batch_stratin(id: UUID, runReq: RunRequest): def get_market_days_in_interval(datefrom, dateto, note = None, id = None): #getting dates from calendat clientTrading = TradingClient(ACCOUNT1_PAPER_API_KEY, ACCOUNT1_PAPER_SECRET_KEY, raw_data=False, paper=True) - calendar_request = GetCalendarRequest(start=datefrom,end=dateto) + calendar_request = GetCalendarRequest(start=datefrom.date(),end=dateto.date()) cal_dates = clientTrading.get_calendar(calendar_request) #list(Calendar) # Calendar @@ -925,7 +926,8 @@ def archive_runner(runner: Runner, strat: StrategyInstance, inter_batch_params: end_positions=strat.state.positions, end_positions_avgp=round(float(strat.state.avgp),3), metrics=results_metrics, - stratvars_toml=runner.run_stratvars_toml + stratvars_toml=runner.run_stratvars_toml, + transferables=strat.state.vars["transferables"] ) #flatten indicators from numpy array @@ -1220,17 +1222,43 @@ def get_archived_runner_header_byID(id: UUID) -> RunArchive: # else: # return 0, res -#vrátí seznam runneru s danym batch_id -def get_archived_runnerslist_byBatchID(batch_id: str): +# #vrátí seznam runneru s danym batch_id +# def get_archived_runnerslist_byBatchID(batch_id: str): +# conn = pool.get_connection() +# try: +# cursor = conn.cursor() +# cursor.execute(f"SELECT runner_id FROM runner_header WHERE batch_id='{str(batch_id)}'") +# runner_list = [row[0] for row in cursor.fetchall()] +# finally: +# pool.release_connection(conn) +# return 0, runner_list + +#update that allows to sort +def get_archived_runnerslist_byBatchID(batch_id: str, sort_order: str = "asc"): + """ + Fetches all runner records by batch_id, sorted by the 'started' column. + + :param batch_id: The batch ID to filter runners by. + :param sort_order: The sort order of the 'started' column. Defaults to 'asc'. + Accepts 'asc' for ascending or 'desc' for descending order. + :return: A tuple with the first element being a status code and the second being the list of runner_ids. + """ + # Validate sort_order + if sort_order.lower() not in ['asc', 'desc']: + return -1, [] # Returning an error code and an empty list in case of invalid sort_order + conn = pool.get_connection() try: cursor = conn.cursor() - cursor.execute(f"SELECT runner_id FROM runner_header WHERE batch_id='{str(batch_id)}'") + query = f"""SELECT runner_id FROM runner_header + WHERE batch_id=? + ORDER BY datetime(started) {sort_order.upper()}""" + cursor.execute(query, (batch_id,)) runner_list = [row[0] for row in cursor.fetchall()] finally: pool.release_connection(conn) return 0, runner_list - + def insert_archive_header(archeader: RunArchive): conn = pool.get_connection() try: @@ -1239,11 +1267,11 @@ def insert_archive_header(archeader: RunArchive): res = c.execute(""" INSERT INTO runner_header - (runner_id, strat_id, batch_id, symbol, name, note, started, stopped, mode, account, bt_from, bt_to, strat_json, settings, ilog_save, profit, trade_count, end_positions, end_positions_avgp, metrics, stratvars_toml) + (runner_id, strat_id, batch_id, symbol, name, note, started, stopped, mode, account, bt_from, bt_to, strat_json, settings, ilog_save, profit, trade_count, end_positions, end_positions_avgp, metrics, stratvars_toml, transferables) VALUES - (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, - (str(archeader.id), str(archeader.strat_id), archeader.batch_id, archeader.symbol, archeader.name, archeader.note, archeader.started, archeader.stopped, archeader.mode, archeader.account, archeader.bt_from, archeader.bt_to, orjson.dumps(archeader.strat_json).decode('utf-8'), orjson.dumps(archeader.settings).decode('utf-8'), archeader.ilog_save, archeader.profit, archeader.trade_count, archeader.end_positions, archeader.end_positions_avgp, orjson.dumps(archeader.metrics, default=json_serial, option=orjson.OPT_PASSTHROUGH_DATETIME).decode('utf-8'), archeader.stratvars_toml)) + (str(archeader.id), str(archeader.strat_id), archeader.batch_id, archeader.symbol, archeader.name, archeader.note, archeader.started, archeader.stopped, archeader.mode, archeader.account, archeader.bt_from, archeader.bt_to, orjson.dumps(archeader.strat_json).decode('utf-8'), orjson.dumps(archeader.settings).decode('utf-8'), archeader.ilog_save, archeader.profit, archeader.trade_count, archeader.end_positions, archeader.end_positions_avgp, orjson.dumps(archeader.metrics, default=json_serial, option=orjson.OPT_PASSTHROUGH_DATETIME).decode('utf-8'), archeader.stratvars_toml, orjson.dumps(archeader.transferables).decode('utf-8'))) #retry not yet supported for statement format above #res = execute_with_retry(c,statement) @@ -1664,10 +1692,15 @@ def preview_indicator_byTOML(id: UUID, indicator: InstantIndicator, save: bool = ##intialize required vars from strat init state.vars["loaded_models"] = {} + #state attributes for martingale sizing mngmt + state.vars["transferables"] = {} + state.vars["transferables"]["martingale"] = dict(cont_loss_series_cnt=0) ##intialize dynamic indicators initialize_dynamic_indicators(state) - + #TODO vazit attached data (z toho potrebuji jen transferables, tzn. najit nejak predchozi runner a prelipnout transferables od zacatku) + #nejspis upravit attach_previous_data a nebo udelat specialni verzi + #attach_previous_data(state) # print("subtype") # function = "ci."+subtype+"."+subtype diff --git a/v2realbot/static/index.html b/v2realbot/static/index.html index f5a825c..b9c7529 100644 --- a/v2realbot/static/index.html +++ b/v2realbot/static/index.html @@ -704,6 +704,10 @@ +