diff --git a/test.db b/test.db new file mode 100644 index 0000000..33e5e0a Binary files /dev/null and b/test.db differ diff --git a/testy/testSqlite3.py b/testy/testSqlite3.py new file mode 100644 index 0000000..0e81d66 --- /dev/null +++ b/testy/testSqlite3.py @@ -0,0 +1,97 @@ +import sqlite3 +from v2realbot.config import DATA_DIR +from v2realbot.utils.utils import json_serial +from uuid import UUID, uuid4 +import json +from datetime import datetime +from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account + +sqlite_db_file = DATA_DIR + "/v2trading.db" +conn = sqlite3.connect(sqlite_db_file) +#standardne vraci pole tuplů, kde clen tuplu jsou sloupce +#conn.row_factory = lambda c, r: json.loads(r[0]) +#conn.row_factory = lambda c, r: r[0] +#conn.row_factory = sqlite3.Row + +#CREATE TABLE +# c = conn.cursor() +# createTable= "CREATE TABLE runner_logs (runner_id varchar(32) NOT NULL, time real NOT NULL, data json NOT NULL);" +# print(c.execute(createTable)) +# sql = ("CREATE INDEX index_runner_logs ON runner_logs (runner_id, time);") +# print(c.execute(sql)) + +#testovaci objekty +insert = dict(time=datetime.now(), side="ddd", rectype=RecordType.BAR, id=uuid4()) +insert_list = [dict(time=datetime.now().timestamp(), side="ddd", rectype=RecordType.BAR, id=uuid4()),dict(time=datetime.now().timestamp(), side="ddd", rectype=RecordType.BAR, id=uuid4()),dict(time=datetime.now().timestamp(), side="ddd", rectype=RecordType.BAR, id=uuid4()),dict(time=datetime.now().timestamp(), side="ddd", rectype=RecordType.BAR, id=uuid4())] + +def insert_log(runner_id: UUID, time: float, logdict: dict): + c = conn.cursor() + json_string = json.dumps(logdict, default=json_serial) + res = c.execute("INSERT INTO runner_logs VALUES (?,?,?)",[str(runner_id), time, json_string]) + conn.commit() + return res.rowcount + +def insert_log_multiple(runner_id: UUID, loglist: list): + c = conn.cursor() + insert_data = [] + for i in loglist: + row = (str(runner_id), i["time"], json.dumps(i, default=json_serial)) + insert_data.append(row) + c.executemany("INSERT INTO runner_logs VALUES (?,?,?)", insert_data) + conn.commit() + return c.rowcount + + # c = conn.cursor() + # json_string = json.dumps(logdict, default=json_serial) + # res = c.execute("INSERT INTO runner_logs VALUES (?,?,?)",[str(runner_id), time, json_string]) + # print(res) + # conn.commit() + # return res + +#returns list of ilog jsons +def read_log_window(runner_id: UUID, timestamp_from: float, timestamp_to: float): + conn.row_factory = lambda c, r: json.loads(r[0]) + c = conn.cursor() + res = c.execute(f"SELECT data FROM runner_logs WHERE runner_id='{str(runner_id)}' AND time >={ts_from} AND time <={ts_to}") + return res.fetchall() + +#returns number of deleted elements +def delete_logs(runner_id: UUID): + c = conn.cursor() + res = c.execute(f"DELETE from runner_logs WHERE runner_id='{str(runner_id)}';") + print(res.rowcount) + conn.commit() + return res.rowcount + +print(insert_log(str(uuid4()), datetime.now().timestamp(), insert)) +c = conn.cursor() +ts_from = 1683108821.08872 +ts_to = 1683108821.08874 +# res = c.execute(f"SELECT runner_id, time, data FROM runner_logs where time > {ts_from} and time <{ts_to}") +# result = res.fetchall() + +# res= delete_logs("7f9866ac-c742-47f4-a329-1d2b6721e781") +# print(res) + +# res = read_log_window(runner_id="33", timestamp_from=11 , timestamp_to=22) +# print(res) + +res = insert_log_multiple(uuid4(), insert_list) +print(res) + +# res = read_log_window("3340e257-d19a-4179-baf3-3b39190acde3", ts_from, ts_to) + +# print(res) + +# for r in res.fetchall(): +# print(dict(r)) + + +#print(res.description) +#print(result) + + + + + + diff --git a/testy/tinyDBselect.py b/testy/tinyDBselect.py index 5a7aae1..ff247ce 100644 --- a/testy/tinyDBselect.py +++ b/testy/tinyDBselect.py @@ -19,14 +19,58 @@ from tinydb.operations import set import json from rich import print -arch_header_file = DATA_DIR + "/arch_header.json" -arch_detail_file = DATA_DIR + "/arch_detail.json" -#db layer to store runner archive -db_arch_h = TinyDB(arch_header_file, default=json_serial) -db_arch_d = TinyDB(arch_detail_file, default=json_serial) +#vyzkouset https://github.com/MrPigss/BetterJSONStorage + + +insert = {'datum': datetime.now(), 'side': "dd", 'name': 'david','id': uuid4(), 'order': "neco"} +class RunnerLogger: + def __init__(self, runner_id: UUID) -> None: + self.runner_id = runner_id + runner_log_file = DATA_DIR + "/runner_log.json" + db_runner_log = TinyDB(runner_log_file, default=json_serial) + +def insert_log_multiple(runner_id: UUID, logList: list): + runner_table = db_runner_log.table(str(runner_id)) + res = runner_table.insert_multiple(logList) + return res + +def insert_log(runner_id: UUID, logdict: dict): + runner_table = db_runner_log.table(str(runner_id)) + res = runner_table.insert(logdict) + return res + + +def read_log_window(runner_id: UUID, timestamp_from: float, timestamp_to: float): + runner_table = db_runner_log.table(str(runner_id)) + res = runner_table.search((where('datum') >= timestamp_from) & (where('datum') <= timestamp_to)) + if len(res) == 0: + return -1, "not found" + return 0, res + +def delete_log(runner_id: UUID): + res = db_runner_log.drop_table(str(runner_id)) + if res is None: + return -1, "not found" + return 0, runner_id + +# runner_id = uuid4() +# for i in range(0,10): +# print(insert_log(runner_id, insert)) + +print(delete_log(runner_id="2459a6ff-a350-44dc-9c14-11cfae07f7e9")) + +print(read_log_window("ae9cdf8f-5cd0-4a49-8cfe-c486e21cb4fa",1,99999999999999)) + + +#2459a6ff-a350-44dc-9c14-11cfae07f7e9 +#ae9cdf8f-5cd0-4a49-8cfe-c486e21cb4fa + + +#db_runner_log.drop_tables() +print(db_runner_log.tables()) # res = db_arch_h.update(set('note', "ahoj"), where('id') == "74aa524e-3ed4-41fb-8166-f20946520344") # print(res) -res = db_arch_d.all() -print(res) \ No newline at end of file +#res = db_runner_log.all() +#print(res) diff --git a/testy/tinyFLUXtest.py b/testy/tinyFLUXtest.py new file mode 100644 index 0000000..fe911e0 --- /dev/null +++ b/testy/tinyFLUXtest.py @@ -0,0 +1,44 @@ + +from typing import Any, List +from uuid import UUID, uuid4 +import pickle +from alpaca.data.historical import StockHistoricalDataClient +from alpaca.data.requests import StockTradesRequest, StockBarsRequest +from alpaca.data.enums import DataFeed +from alpaca.data.timeframe import TimeFrame +from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account +from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange +from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial +from datetime import datetime +from threading import Thread, current_thread, Event, enumerate +from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR +import importlib +from queue import Queue +#from tinydb import TinyDB, Query, where +#from tinydb.operations import set +import json +from rich import print +from tinyflux import Point, TinyFlux + + +runner_log_file = DATA_DIR + "/runner_flux__log.json" +#db layer to store runner archive +db_runner_log = TinyFlux(runner_log_file) + +insert_dict = {'datum': datetime.now(), 'side': "dd", 'name': 'david','id': uuid4(), 'order': "neco"} +#json.dumps(insert_dict, default=json_serial) +p1 = Point(time=datetime.now(), tags=insert_dict) + +db_runner_log.insert(p1) + +res=db_runner_log.all() +print(res) + + +# #db_runner_log.drop_table('hash') +# res = runner_table.get(where('side') == "dd") +# print(res) +# # res = db_arch_h.update(set('note', "ahoj"), where('id') == "74aa524e-3ed4-41fb-8166-f20946520344") +# # print(res) +# res = runner_table.all() +# print(res) diff --git a/testy/tinydbTest.py b/testy/tinydbTest.py index 62a62c4..fb3ef5e 100644 --- a/testy/tinydbTest.py +++ b/testy/tinydbTest.py @@ -114,6 +114,10 @@ db = TinyDB(db_file, default=json_serial) db.truncate() insert = {'datum': datetime.now(), 'side': OrderSide.BUY, 'name': 'david','id': uuid4(), 'order': orderList} + + + + #insert record db.insert(a.__dict__) diff --git a/v2realbot/ENTRY_backtest_strategyVykladaci.py b/v2realbot/ENTRY_backtest_strategyVykladaci.py index ce8098d..9dcaa02 100644 --- a/v2realbot/ENTRY_backtest_strategyVykladaci.py +++ b/v2realbot/ENTRY_backtest_strategyVykladaci.py @@ -191,6 +191,8 @@ def next(data, state: StrategyState): state.vars.blockbuy = 0 return 0 + state.ilog(e="-----") + try: ## slope vyresi rychlé sesupy - jeste je treba podchytit pomalejsi sesupy @@ -245,6 +247,10 @@ def next(data, state: StrategyState): # state.ilog(e="Slope - MA"+str(state.indicators.slopeMA[-1])) else: + #pokud plnime historii musime ji plnit od zacatku, vsehcny idenitifkatory maji spolecny time + #kvuli spravnemu zobrazovani na gui + state.indicators.slope.append(0) + state.indicators.slopeMA.append(0) state.ilog(e="Slope - not enough data", slope_lookback=slope_lookback) except Exception as e: @@ -357,7 +363,7 @@ def next(data, state: StrategyState): #HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru lp = state.interface.get_last_price(symbol=state.symbol) - state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, stratvars=state.vars) + state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, data=data, stratvars=state.vars) #maxSlopeMA = -0.03 #SLOPE ANGLE PROTECTIONs @@ -461,7 +467,7 @@ def init(state: StrategyState): state.indicators['slope'] = [] state.indicators['slopeMA'] = [] #static indicators - those not series based - state.statinds['angle'] = {} + state.statinds['angle'] = dict(minimum_slope=state.vars["minimum_slope"]) state.vars["ticks2reset_backup"] = state.vars.ticks2reset def main(): @@ -475,7 +481,7 @@ def main(): name = os.path.basename(__file__) se = Event() pe = Event() - s = StrategyOrderLimitVykladaci(name = name, symbol = "BAC", account=Account.ACCOUNT1, next=next, init=init, stratvars=stratvars, open_rush=10, close_rush=0, pe=pe, se=se) + s = StrategyOrderLimitVykladaci(name = name, symbol = "BAC", account=Account.ACCOUNT1, next=next, init=init, stratvars=stratvars, open_rush=10, close_rush=0, pe=pe, se=se, ilog_save=True) s.set_mode(mode = Mode.BT, debug = False, start = datetime(2023, 4, 14, 10, 42, 0, 0, tzinfo=zoneNY), diff --git a/v2realbot/__pycache__/config.cpython-310.pyc b/v2realbot/__pycache__/config.cpython-310.pyc index e3b2ecb..d49f68a 100644 Binary files a/v2realbot/__pycache__/config.cpython-310.pyc and b/v2realbot/__pycache__/config.cpython-310.pyc differ diff --git a/v2realbot/common/__pycache__/model.cpython-310.pyc b/v2realbot/common/__pycache__/model.cpython-310.pyc index 9978461..cd3cb2d 100644 Binary files a/v2realbot/common/__pycache__/model.cpython-310.pyc and b/v2realbot/common/__pycache__/model.cpython-310.pyc differ diff --git a/v2realbot/common/model.py b/v2realbot/common/model.py index e6c038b..c62b13f 100644 --- a/v2realbot/common/model.py +++ b/v2realbot/common/model.py @@ -58,20 +58,21 @@ class RunRequest(BaseModel): mode: Mode note: Optional[str] = None debug: bool = False + ilog_save: bool = False bt_from: datetime = None bt_to: datetime = None cash: int = 100000 - - class RunnerView(BaseModel): id: UUID + strat_id: UUID run_started: Optional[datetime] = None run_mode: Mode run_name: Optional[str] = None run_note: Optional[str] = None run_account: Account + run_ilog_save: Optional[bool] = False run_symbol: Optional[str] = None run_trade_count: Optional[int] = 0 run_profit: Optional[float] = 0 @@ -83,12 +84,14 @@ class RunnerView(BaseModel): #Running instance - not persisted class Runner(BaseModel): id: UUID + strat_id: UUID run_started: Optional[datetime] = None run_mode: Mode run_account: Account run_symbol: Optional[str] = None run_name: Optional[str] = None run_note: Optional[str] = None + run_ilog_save: Optional[bool] = False run_trade_count: Optional[int] run_profit: Optional[float] run_positions: Optional[int] @@ -174,6 +177,8 @@ class RunArchive(BaseModel): bt_from: Optional[datetime] = None bt_to: Optional[datetime] = None stratvars: Optional[dict] = None + settings: Optional[dict] = None + ilog_save: Optional[bool] = False profit: float = 0 trade_count: int = 0 end_positions: int = 0 diff --git a/v2realbot/config.py b/v2realbot/config.py index a272a83..bdec1cb 100644 --- a/v2realbot/config.py +++ b/v2realbot/config.py @@ -2,6 +2,8 @@ from alpaca.data.enums import DataFeed from v2realbot.enums.enums import Mode, Account, FillCondition from appdirs import user_data_dir + +LOG_RUNNER_EVENTS = False #no print in console QUIET_MODE = False #how many consecutive trades with the fill price are necessary for LIMIT fill to happen in backtesting diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py index 92eee53..70a259d 100644 --- a/v2realbot/controller/services.py +++ b/v2realbot/controller/services.py @@ -6,11 +6,12 @@ from alpaca.data.requests import StockTradesRequest, StockBarsRequest from alpaca.data.enums import DataFeed from alpaca.data.timeframe import TimeFrame from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account -from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange -from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial +from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange, Bar +from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours +from v2realbot.utils.ilog import delete_logs from datetime import datetime from threading import Thread, current_thread, Event, enumerate -from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR +from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT import importlib from queue import Queue from tinydb import TinyDB, Query, where @@ -117,7 +118,7 @@ def delete_stratin(id: UUID): def inject_stratvars(id: UUID, stratvars_parsed_new: AttributeDict, stratvars_parsed_old: AttributeDict): for i in db.runners: - if str(i.id) == str(id): + if str(i.strat_id) == str(id): #inject only those changed, some of them cannot be changed (for example pendingbuys) changed_keys = [] @@ -180,7 +181,7 @@ def modify_stratin_running(si: StrategyInstance, id: UUID): ##enable realtime chart - inject given queue for strategy instance ##webservice listens to this queue -async def stratin_realtime_on(id: UUID, rtqueue: Queue): +async def runner_realtime_on(id: UUID, rtqueue: Queue): for i in db.runners: if str(i.id) == str(id): i.run_instance.rtqueue = rtqueue @@ -189,7 +190,7 @@ async def stratin_realtime_on(id: UUID, rtqueue: Queue): print("ERROR NOT FOUND") return -2 -async def stratin_realtime_off(id: UUID): +async def runner_realtime_off(id: UUID): for i in db.runners: if str(i.id) == str(id): i.run_instance.rtqueue = None @@ -199,7 +200,7 @@ async def stratin_realtime_off(id: UUID): return -2 ##controller (run_stratefy, pause, stop, reload_params) -def pause_stratin(id: UUID): +def pause_runner(id: UUID): for i in db.runners: print(i.id) if str(i.id) == id: @@ -215,7 +216,7 @@ def pause_stratin(id: UUID): print("no ID found") return (-1, "not running instance found") -def stop_stratin(id: UUID = None): +def stop_runner(id: UUID = None): chng = [] for i in db.runners: #print(i['id']) @@ -236,6 +237,13 @@ def stop_stratin(id: UUID = None): return (-2, "not found" + str(id)) def is_stratin_running(id: UUID): + for i in db.runners: + if str(i.strat_id) == str(id): + if i.run_started is not None and i.run_stopped is None: + return True + return False + +def is_runner_running(id: UUID): for i in db.runners: if str(i.id) == str(id): if i.run_started is not None and i.run_stopped is None: @@ -280,14 +288,14 @@ def capsule(target: object, db: object): i.run_pause_ev = None i.run_stop_ev = None #ukladame radek do historie (pozdeji refactor) - save_history(id=i.id, st=target, runner=i, reason=reason) + save_history(id=i.strat_id, st=target, runner=i, reason=reason) #store in archive header and archive detail archive_runner(runner=i, strat=target) #mazeme runner po skonceni instance db.runners.remove(i) print("Runner STOPPED") - +#stratin run def run_stratin(id: UUID, runReq: RunRequest): if runReq.mode == Mode.BT: if runReq.bt_from is None: @@ -336,7 +344,12 @@ def run_stratin(id: UUID, runReq: RunRequest): next=next, init=init, stratvars=stratvars, - open_rush=open_rush, close_rush=close_rush, pe=pe, se=se) + open_rush=open_rush, + close_rush=close_rush, + pe=pe, + se=se, + runner_id=id, + ilog_save=runReq.ilog_save) print("instance vytvorena", instance) #set mode if runReq.mode == Mode.LIVE or runReq.mode == Mode.PAPER: @@ -359,7 +372,9 @@ def run_stratin(id: UUID, runReq: RunRequest): vlakno.start() print("Spuštěna", instance.name) ##storing the attributtes - pozor pri stopu je zase odstranit - runner = Runner(id = i.id, + #id runneru je nove id, stratin se dava dalsiho parametru + runner = Runner(id = id, + strat_id = i.id, run_started = datetime.now(zoneNY), run_pause_ev = pe, run_name = name, @@ -368,13 +383,14 @@ def run_stratin(id: UUID, runReq: RunRequest): run_stop_ev = se, run_thread = vlakno, run_account = runReq.account, + run_ilog_save = runReq.ilog_save, run_mode = runReq.mode, run_instance = instance) db.runners.append(runner) print(db.runners) print(i) print(enumerate()) - return (0, i.id) + return (0, id) except Exception as e: return (-2, "Exception: "+str(e)) return (-2, "not found") @@ -403,9 +419,17 @@ def archive_runner(runner: Runner, strat: StrategyInstance): else: bp_from = None bp_to = None - id = uuid4() - runArchive: RunArchive = RunArchive(id = id, - strat_id = runner.id, + + settings = dict(resolution=strat.state.timeframe, + rectype=strat.state.rectype, + configs=dict( + BT_FILL_CONS_TRADES_REQUIRED=BT_FILL_CONS_TRADES_REQUIRED, + BT_FILL_LOG_SURROUNDING_TRADES=BT_FILL_LOG_SURROUNDING_TRADES, + BT_FILL_CONDITION_BUY_LIMIT=BT_FILL_CONDITION_BUY_LIMIT, + BT_FILL_CONDITION_SELL_LIMIT=BT_FILL_CONDITION_SELL_LIMIT)) + + runArchive: RunArchive = RunArchive(id = runner.id, + strat_id = runner.strat_id, name=runner.run_name, note=runner.run_note, symbol=runner.run_symbol, @@ -413,9 +437,11 @@ def archive_runner(runner: Runner, strat: StrategyInstance): stopped=runner.run_stopped, mode=runner.run_mode, account=runner.run_account, + ilog_save=runner.run_ilog_save, bt_from=bp_from, bt_to = bp_to, stratvars = strat.state.vars, + settings = settings, profit=round(float(strat.state.profit),2), trade_count=len(strat.state.tradeList), end_positions=strat.state.positions, @@ -434,7 +460,7 @@ def archive_runner(runner: Runner, strat: StrategyInstance): print("is not numpy", key, value) flattened_indicators[key]= value - runArchiveDetail: RunArchiveDetail = RunArchiveDetail(id = id, + runArchiveDetail: RunArchiveDetail = RunArchiveDetail(id = runner.id, name=runner.run_name, bars=strat.state.bars, indicators=flattened_indicators, @@ -452,14 +478,15 @@ def get_all_archived_runners(): res = db_arch_h.all() return 0, res -#delete runner in archive and archive detail +#delete runner in archive and archive detail and runner logs def delete_archived_runners_byID(id: UUID): try: resh = db_arch_h.remove(where('id') == id) resd = db_arch_d.remove(where('id') == id) - if len(resh) == 0 or len(resd) == 0: - return -1, "not found "+str(resh) + " " + str(resd) - return 0, str(resh) + " " + str(resd) + reslogs = delete_logs(id) + if len(resh) == 0 or len(resd) == 0 or reslogs ==0: + return -1, "not found "+str(resh) + " " + str(resd) + " " + str(reslogs) + return 0, str(resh) + " " + str(resd) + " " + str(reslogs) except Exception as e: return -2, str(e) @@ -493,7 +520,30 @@ def get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, datetim #datetime_object_from = datetime(2023, 2, 27, 18, 51, 38, tzinfo=datetime.timezone.utc) #datetime_object_to = datetime(2023, 2, 27, 21, 51, 39, tzinfo=datetime.timezone.utc) bar_request = StockBarsRequest(symbol_or_symbols=symbol,timeframe=timeframe, start=datetime_object_from, end=datetime_object_to, feed=DataFeed.SIP) + #print("before df") bars = client.get_stock_bars(bar_request) + result = [] + for row in bars.data[symbol]: + if is_open_hours(row.timestamp): + result.append(row) + + # print("df", bars) + # print(bars.info()) + # bars = bars.droplevel(0) + # print("after drop", bars) + # print(bars.info()) + # print("before tz", bars) + # bars = bars.tz_convert('America/New_York') + # print("before time", bars) + # bars = bars.between_time("9:30","16:00") + # print("after time", bars) + # bars = bars.reset_index() + # bars = bars.to_dict(orient="records") + #print(ohlcvList) + #ohlcvList = {} + + #bars = {} + return 0, bars.data[symbol] except Exception as e: return -2, str(e) diff --git a/v2realbot/main.py b/v2realbot/main.py index 33e2221..4710279 100644 --- a/v2realbot/main.py +++ b/v2realbot/main.py @@ -13,6 +13,7 @@ from fastapi.security import APIKeyHeader import uvicorn from uuid import UUID import v2realbot.controller.services as cs +from v2realbot.utils.ilog import get_log_window from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade, RunArchive, RunArchiveDetail, Bar, RunArchiveChange from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, WebSocketException, Cookie, Query from fastapi.responses import HTMLResponse, FileResponse @@ -95,14 +96,14 @@ async def websocket_endpoint( api_key: Annotated[str, Depends(get_api_key)], ): await websocket.accept() - if not cs.is_stratin_running(runner_id): + if not cs.is_runner_running(runner_id): #await websocket.close(code=status.WS_1003_UNSUPPORTED_DATA, reason="Strat not running") - raise WebSocketException(code=status.WS_1003_UNSUPPORTED_DATA, reason="Stratin not running.") + raise WebSocketException(code=status.WS_1003_UNSUPPORTED_DATA, reason="Runner not running.") return else: print("stratin exists") q: Queue = Queue() - await cs.stratin_realtime_on(id=runner_id, rtqueue=q) + await cs.runner_realtime_on(id=runner_id, rtqueue=q) # tx task; reads data from queue and sends to websocket async def websocket_tx_task(ws, _q): @@ -158,7 +159,7 @@ async def websocket_endpoint( print("CLIENT DISCONNECTED for", runner_id) finally: q.put("break") - await cs.stratin_realtime_off(runner_id) + await cs.runner_realtime_off(runner_id) @app.get("/threads/", dependencies=[Depends(api_key_auth)]) def _get_all_threads(): @@ -227,16 +228,16 @@ def _run_stratin(stratin_id: UUID, runReq: RunRequest): elif res < 0: raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error: {res}:{id}") -@app.put("/stratins/{stratin_id}/pause", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK) -def _pause_stratin(stratin_id): - res, id = cs.pause_stratin(id=stratin_id) +@app.put("/runners/{runner_id}/pause", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK) +def _pause_runner(runner_id): + res, id = cs.pause_runner(id=runner_id) if res == 0: return id elif res < 0: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{id}") -@app.put("/stratins/{stratin_id}/stop", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK) -def _stop_stratin(stratin_id): - res, id = cs.stop_stratin(id=stratin_id) +@app.put("/runners/{runner_id}/stop", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK) +def _stop_runner(runner_id): + res, id = cs.stop_runner(id=runner_id) if res == 0: return id elif res < 0: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{id}") @@ -248,9 +249,9 @@ def _delete_stratin(stratin_id): elif res < 0: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{id}") -@app.put("/stratins/stop", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK) -def stop_all_stratins(): - res, id = cs.stop_stratin() +@app.put("/runners/stop", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK) +def stop_all_runners(): + res, id = cs.stop_runner() if res == 0: return id elif res < 0: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{id}") @@ -310,6 +311,15 @@ def _get_archived_runner_details_byID(runner_id) -> RunArchiveDetail: else: raise HTTPException(status_code=404, detail=f"No runner with id: {runner_id} a {set}") +#get archived runners detail by id +@app.get("/archived_runners_log/{runner_id}", dependencies=[Depends(api_key_auth)]) +def _get_archived_runner_log_byID(runner_id: UUID, timestamp_from: float, timestamp_to: float) -> list[dict]: + res = get_log_window(runner_id,timestamp_from, timestamp_to) + if len(res) > 0: + return res + else: + raise HTTPException(status_code=404, detail=f"No logs found with id: {runner_id} and between {timestamp_from} and {timestamp_to}") + #get alpaca history bars @app.get("/history_bars/", dependencies=[Depends(api_key_auth)]) def _get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, datetime_object_to: datetime, timeframe_amount: int, timeframe_unit: TimeFrameUnit) -> list[Bar]: @@ -317,7 +327,7 @@ def _get_alpaca_history_bars(symbol: str, datetime_object_from: datetime, dateti if res == 0: return set else: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found") + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"No data found {res} {set}") #join cekej na dokonceni vsech diff --git a/v2realbot/static/index.html b/v2realbot/static/index.html index 7fbdd62..53de61e 100644 --- a/v2realbot/static/index.html +++ b/v2realbot/static/index.html @@ -1,5 +1,5 @@ - +
@@ -51,12 +51,16 @@ -| Id | +StratId | Started | Mode | Symbol | -Account | +Account | +ilog | Paused | Profit | Trades | @@ -152,6 +158,7 @@ + @@ -159,20 +166,22 @@|||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Id | +StratId | Name | -Symbol | +Sym | Note | started | stopped | mode | account | bt_from | -bt_to | +bt_to | +ilog | stratvars | profit | -tradecnt | -end_pos | -end_pos_avgp | +trade | +pos | +pos_avgp | open |