Feature/market attribute (#185)
* RunManagerRecord class has a new attribute market. Market enum is imported. * row_to_runmanager function considers market column * add_run_manager_record and update_run_manager_record functions are changed. fetch_all_markets_in_run_manager is new. * new Market enumeration class is defined * market_value used for job scheduling. start and stop functions have modifications of market parameter input * new is_market_day function + modifications of get_todays_market_times function * market attribute set default to US * row_to_runmanager function has no string formatter for market attribute * add_run_manager_record function adn update_run_manager_record function update the DB column market based on record.market data * start_runman_record and stop_runman_record have got no market parameter * get_todays_market_times function is changed * default value for market atribute is Market.US * update_run_manager_record function has no if condition for market key * market_value deleted, used enumaration value Market.US instead of string US * get_todays_market_times has a new if condition for Market.CRYPTO * update includes market column in the run_manager table * market attribute in Run Manager record has value given by enumeration as Market.US * documentation of changes made in the branch * remove README_feature_market.md * back to original state * Delete README_feature_market.md * _start_runman_record has an additional else condition * is_market_day renamed to is_US_market_day * transferables column added into runner_header table
This commit is contained in:
@ -5,7 +5,7 @@ from rich import print
|
||||
from typing import Any, Optional, List, Union
|
||||
from datetime import datetime, date
|
||||
from pydantic import BaseModel, Field
|
||||
from v2realbot.enums.enums import Mode, Account, SchedulerStatus, Moddus
|
||||
from v2realbot.enums.enums import Mode, Account, SchedulerStatus, Moddus, Market
|
||||
from alpaca.data.enums import Exchange
|
||||
|
||||
|
||||
@ -159,6 +159,7 @@ class RunManagerRecord(BaseModel):
|
||||
mode: Mode
|
||||
note: Optional[str] = None
|
||||
ilog_save: bool = False
|
||||
market: Optional[Market] = Market.US
|
||||
bt_from: Optional[datetime] = None
|
||||
bt_to: Optional[datetime] = None
|
||||
#weekdays filter
|
||||
|
||||
@ -5,9 +5,7 @@ import v2realbot.controller.services as cs
|
||||
|
||||
#prevede dict radku zpatky na objekt vcetme retypizace
|
||||
def row_to_runmanager(row: dict) -> RunManagerRecord:
|
||||
|
||||
is_running = cs.is_runner_running(row['runner_id']) if row['runner_id'] else False
|
||||
|
||||
res = RunManagerRecord(
|
||||
moddus=row['moddus'],
|
||||
id=row['id'],
|
||||
@ -17,6 +15,7 @@ def row_to_runmanager(row: dict) -> RunManagerRecord:
|
||||
account=row['account'],
|
||||
note=row['note'],
|
||||
ilog_save=bool(row['ilog_save']),
|
||||
market=row['market'] if row['market'] is not None else None,
|
||||
bt_from=datetime.fromisoformat(row['bt_from']) if row['bt_from'] else None,
|
||||
bt_to=datetime.fromisoformat(row['bt_to']) if row['bt_to'] else None,
|
||||
weekdays_filter=[int(x) for x in row['weekdays_filter'].split(',')] if row['weekdays_filter'] else [],
|
||||
|
||||
@ -172,14 +172,14 @@ def add_run_manager_record(new_record: RunManagerRecord):
|
||||
# Construct a suitable INSERT query based on your RunManagerRecord fields
|
||||
insert_query = """
|
||||
INSERT INTO run_manager (moddus, id, strat_id, symbol,account, mode, note,ilog_save,
|
||||
bt_from, bt_to, weekdays_filter, batch_id,
|
||||
market, bt_from, bt_to, weekdays_filter, batch_id,
|
||||
start_time, stop_time, status, last_processed,
|
||||
history, valid_from, valid_to, testlist_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
|
||||
"""
|
||||
values = [
|
||||
new_record.moddus, str(new_record.id), str(new_record.strat_id), new_record.symbol, new_record.account, new_record.mode, new_record.note,
|
||||
int(new_record.ilog_save),
|
||||
int(new_record.ilog_save), new_record.market,
|
||||
new_record.bt_from.isoformat() if new_record.bt_from is not None else None,
|
||||
new_record.bt_to.isoformat() if new_record.bt_to is not None else None,
|
||||
",".join(str(x) for x in new_record.weekdays_filter) if new_record.weekdays_filter else None,
|
||||
|
||||
@ -103,4 +103,10 @@ class StartBarAlign(str, Enum):
|
||||
RANDOM = first bar starts when first trade occurs
|
||||
"""
|
||||
ROUND = "round"
|
||||
RANDOM = "random"
|
||||
RANDOM = "random"
|
||||
|
||||
class Market(str, Enum):
|
||||
US = "US"
|
||||
CRYPTO = "CRYPTO"
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ from uuid import UUID
|
||||
from typing import Any, List, Tuple
|
||||
from uuid import UUID, uuid4
|
||||
from v2realbot.enums.enums import Moddus, SchedulerStatus, RecordType, StartBarAlign, Mode, Account, OrderSide
|
||||
from v2realbot.common.model import RunManagerRecord, StrategyInstance, RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveViewPagination, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem, InstantIndicator, DataTablesRequest
|
||||
from v2realbot.common.model import RunManagerRecord, StrategyInstance, RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveViewPagination, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem, InstantIndicator, DataTablesRequest, Market
|
||||
from v2realbot.utils.utils import validate_and_format_time, AttributeDict, zoneNY, zonePRG, safe_get, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram, concatenate_weekdays, transform_data
|
||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||
from datetime import datetime
|
||||
@ -116,7 +116,8 @@ def initialize_jobs(run_manager_records: RunManagerRecord = None):
|
||||
scheduler.add_job(start_runman_record, start_trigger, id=f"scheduler_start_{record.id}", args=[record.id])
|
||||
scheduler.add_job(stop_runman_record, stop_trigger, id=f"scheduler_stop_{record.id}", args=[record.id])
|
||||
|
||||
#scheduler.add_job(print_hello, 'interval', seconds=10, id=f"scheduler_testinterval")
|
||||
#scheduler.add_job(print_hello, 'interval', seconds=10, id=
|
||||
# f"scheduler_testinterval")
|
||||
scheduled_jobs = scheduler.get_jobs()
|
||||
print(f"APS jobs refreshed ({len(scheduled_jobs)})")
|
||||
current_jobs_dict = format_apscheduler_jobs(scheduled_jobs)
|
||||
@ -124,9 +125,9 @@ def initialize_jobs(run_manager_records: RunManagerRecord = None):
|
||||
return 0, current_jobs_dict
|
||||
|
||||
#zastresovaci funkce resici error handling a printing
|
||||
def start_runman_record(id: UUID, market = "US", debug_date = None):
|
||||
def start_runman_record(id: UUID, debug_date = None):
|
||||
record = None
|
||||
res, record, msg = _start_runman_record(id=id, market=market, debug_date=debug_date)
|
||||
res, record, msg = _start_runman_record(id=id, debug_date=debug_date)
|
||||
|
||||
if record is not None:
|
||||
market_time_now = datetime.now().astimezone(zoneNY) if debug_date is None else debug_date
|
||||
@ -165,8 +166,8 @@ def update_runman_record(record: RunManagerRecord):
|
||||
err_msg= f"STOP: Error updating {record.id} errir {set} with values {record}"
|
||||
return -2, err_msg#toto stopne zpracovani dalsich zaznamu pri chybe, zvazit continue
|
||||
|
||||
def stop_runman_record(id: UUID, market = "US", debug_date = None):
|
||||
res, record, msg = _stop_runman_record(id=id, market=market, debug_date=debug_date)
|
||||
def stop_runman_record(id: UUID, debug_date = None):
|
||||
res, record, msg = _stop_runman_record(id=id, debug_date=debug_date)
|
||||
#results : 0 - ok, -1 not running/already running/not specific, -2 error
|
||||
|
||||
#report vzdy zapiseme do history, pokud je record not None, pripadna chyba se stala po dotazeni recordu
|
||||
@ -196,7 +197,7 @@ def stop_runman_record(id: UUID, market = "US", debug_date = None):
|
||||
print(f"STOP JOB: {id} FINISHED")
|
||||
|
||||
#start function that is called from the job
|
||||
def _start_runman_record(id: UUID, market = "US", debug_date = None):
|
||||
def _start_runman_record(id: UUID, debug_date = None):
|
||||
print(f"Start scheduled record {id}")
|
||||
|
||||
record : RunManagerRecord = None
|
||||
@ -207,15 +208,16 @@ def _start_runman_record(id: UUID, market = "US", debug_date = None):
|
||||
|
||||
record = result
|
||||
|
||||
if market is not None and market == "US":
|
||||
res, sada = sch.get_todays_market_times(market=market, debug_date=debug_date)
|
||||
if record.market == Market.US or record.market == Market.CRYPTO:
|
||||
res, sada = sch.get_todays_market_times(market=record.market, debug_date=debug_date)
|
||||
if res == 0:
|
||||
market_time_now, market_open_datetime, market_close_datetime = sada
|
||||
print(f"OPEN:{market_open_datetime} CLOSE:{market_close_datetime}")
|
||||
else:
|
||||
sada = f"Market {market} Error getting market times (CLOSED): " + str(sada)
|
||||
sada = f"Market {record.market} Error getting market times (CLOSED): " + str(sada)
|
||||
return res, record, sada
|
||||
|
||||
else:
|
||||
print("Market type is unknown.")
|
||||
if cs.is_stratin_running(record.strat_id):
|
||||
return -1, record, f"Stratin {record.strat_id} is already running"
|
||||
|
||||
@ -229,7 +231,7 @@ def _start_runman_record(id: UUID, market = "US", debug_date = None):
|
||||
return 0, record, record.runner_id
|
||||
|
||||
#stop function that is called from the job
|
||||
def _stop_runman_record(id: UUID, market = "US", debug_date = None):
|
||||
def _stop_runman_record(id: UUID, debug_date = None):
|
||||
record = None
|
||||
#get all records
|
||||
print(f"Stopping record {id}")
|
||||
@ -304,5 +306,5 @@ if __name__ == "__main__":
|
||||
# print(f"CALL FINISHED, with {debug_date} RESULT: {res}, {result}")
|
||||
|
||||
|
||||
res, result = stop_runman_record(id=id, market = "US", debug_date = debug_date)
|
||||
res, result = stop_runman_record(id=id, debug_date = debug_date)
|
||||
print(f"CALL FINISHED, with {debug_date} RESULT: {res}, {result}")
|
||||
@ -2,10 +2,10 @@ import json
|
||||
import datetime
|
||||
import v2realbot.controller.services as cs
|
||||
import v2realbot.controller.run_manager as rm
|
||||
from v2realbot.common.model import RunnerView, RunManagerRecord, StrategyInstance, Runner, RunRequest, Trade, RunArchive, RunArchiveView, RunArchiveViewPagination, RunArchiveDetail, Bar, RunArchiveChange, TestList, ConfigItem, InstantIndicator, DataTablesRequest, AnalyzerInputs
|
||||
from v2realbot.common.model import RunnerView, RunManagerRecord, StrategyInstance, Runner, RunRequest, Trade, RunArchive, RunArchiveView, RunArchiveViewPagination, RunArchiveDetail, Bar, RunArchiveChange, TestList, ConfigItem, InstantIndicator, DataTablesRequest, AnalyzerInputs, Market
|
||||
from uuid import uuid4, UUID
|
||||
from v2realbot.utils.utils import json_serial, send_to_telegram, zoneNY, zonePRG, fetch_calendar_data
|
||||
from datetime import datetime, timedelta
|
||||
from v2realbot.utils.utils import json_serial, send_to_telegram, zoneNY, zonePRG, zoneUTC, fetch_calendar_data
|
||||
from datetime import datetime, timedelta, time
|
||||
from traceback import format_exc
|
||||
from rich import print
|
||||
import requests
|
||||
@ -18,9 +18,18 @@ from v2realbot.config import WEB_API_KEY
|
||||
#naplanovany jako samostatni job a triggerován pouze jednou v daný čas pro start a stop
|
||||
#novy kod v aps_scheduler.py
|
||||
|
||||
def get_todays_market_times(market = "US", debug_date = None):
|
||||
def is_US_market_day(date):
|
||||
cal_dates = fetch_calendar_data(date, date)
|
||||
if len(cal_dates) == 0:
|
||||
print("Today is not a market day.")
|
||||
return False, cal_dates
|
||||
else:
|
||||
print("Market is open")
|
||||
return True, cal_dates
|
||||
|
||||
def get_todays_market_times(market, debug_date = None):
|
||||
try:
|
||||
if market == "US":
|
||||
if market == Market.US:
|
||||
#zjistit vsechny podminky - mozna loopovat - podminky jsou vlevo
|
||||
if debug_date is not None:
|
||||
nowNY = debug_date
|
||||
@ -28,17 +37,20 @@ def get_todays_market_times(market = "US", debug_date = None):
|
||||
nowNY = datetime.now().astimezone(zoneNY)
|
||||
nowNY_date = nowNY.date()
|
||||
#is market open - nyni pouze US
|
||||
cal_dates = fetch_calendar_data(nowNY_date, nowNY_date)
|
||||
|
||||
if len(cal_dates) == 0:
|
||||
print("No Market Day today")
|
||||
return -1, "Market Closed"
|
||||
stat, calendar_dates = is_US_market_day(nowNY_date)
|
||||
if stat:
|
||||
#zatim podpora pouze main session
|
||||
|
||||
#pouze main session
|
||||
market_open_datetime = zoneNY.localize(cal_dates[0].open)
|
||||
market_close_datetime = zoneNY.localize(cal_dates[0].close)
|
||||
return 0, (nowNY, market_open_datetime, market_close_datetime)
|
||||
market_open_datetime = zoneNY.localize(calendar_dates[0].open)
|
||||
market_close_datetime = zoneNY.localize(calendar_dates[0].close)
|
||||
return 0, (nowNY, market_open_datetime, market_close_datetime)
|
||||
else:
|
||||
return -1, "Market is closed."
|
||||
elif market == Market.CRYPTO:
|
||||
now_market_datetime = datetime.now().astimezone(zoneUTC)
|
||||
market_open_datetime = datetime.combine(datetime.now(), time.min)
|
||||
matket_close_datetime = datetime.combine(datetime.now(), time.max)
|
||||
return 0, (now_market_datetime, market_open_datetime, matket_close_datetime)
|
||||
else:
|
||||
return -1, "Market not supported"
|
||||
except Exception as e:
|
||||
|
||||
97
v2trading_create_db.sql
Normal file
97
v2trading_create_db.sql
Normal file
@ -0,0 +1,97 @@
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE IF NOT EXISTS "test_list" (
|
||||
"id" varchar(32) NOT NULL,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"dates" json NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "runner_detail" (
|
||||
"runner_id" varchar(32) NOT NULL,
|
||||
"data" json NOT NULL,
|
||||
PRIMARY KEY("runner_id")
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "runner_header" (
|
||||
"runner_id" varchar(32) NOT NULL,
|
||||
"strat_id" TEXT,
|
||||
"batch_id" TEXT,
|
||||
"symbol" TEXT,
|
||||
"name" TEXT,
|
||||
"note" TEXT,
|
||||
"started" TEXT,
|
||||
"stopped" TEXT,
|
||||
"mode" TEXT,
|
||||
"account" TEXT,
|
||||
"bt_from" TEXT,
|
||||
"bt_to" TEXT,
|
||||
"strat_json" TEXT,
|
||||
"settings" TEXT,
|
||||
"ilog_save" INTEGER,
|
||||
"profit" NUMERIC,
|
||||
"trade_count" INTEGER,
|
||||
"end_positions" INTEGER,
|
||||
"end_positions_avgp" NUMERIC,
|
||||
"metrics" TEXT,
|
||||
"stratvars_toml" TEXT,
|
||||
"transferables" TEXT,
|
||||
PRIMARY KEY("runner_id")
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "config_table" (
|
||||
"id" INTEGER,
|
||||
"item_name" TEXT NOT NULL,
|
||||
"json_data" JSON NOT NULL,
|
||||
"item_lang" TEXT,
|
||||
PRIMARY KEY("id" AUTOINCREMENT)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "runner_logs" (
|
||||
"runner_id" varchar(32) NOT NULL,
|
||||
"time" real NOT NULL,
|
||||
"data" json NOT NULL
|
||||
);
|
||||
CREATE TABLE "run_manager" (
|
||||
"moddus" TEXT NOT NULL,
|
||||
"id" varchar(32),
|
||||
"strat_id" varchar(32) NOT NULL,
|
||||
"symbol" TEXT,
|
||||
"account" TEXT NOT NULL,
|
||||
"mode" TEXT NOT NULL,
|
||||
"note" TEXT,
|
||||
"ilog_save" BOOLEAN,
|
||||
"bt_from" TEXT,
|
||||
"bt_to" TEXT,
|
||||
"weekdays_filter" TEXT,
|
||||
"batch_id" TEXT,
|
||||
"start_time" TEXT NOT NULL,
|
||||
"stop_time" TEXT NOT NULL,
|
||||
"status" TEXT NOT NULL,
|
||||
"last_processed" TEXT,
|
||||
"history" TEXT,
|
||||
"valid_from" TEXT,
|
||||
"valid_to" TEXT,
|
||||
"testlist_id" TEXT,
|
||||
"runner_id" varchar2(32),
|
||||
"market" TEXT,
|
||||
PRIMARY KEY("id")
|
||||
);
|
||||
CREATE INDEX idx_moddus ON run_manager (moddus);
|
||||
CREATE INDEX idx_status ON run_manager (status);
|
||||
CREATE INDEX idx_status_moddus ON run_manager (status, moddus);
|
||||
CREATE INDEX idx_valid_from_to ON run_manager (valid_from, valid_to);
|
||||
CREATE INDEX idx_stopped_batch_id ON runner_header (stopped, batch_id);
|
||||
CREATE INDEX idx_search_value ON runner_header (strat_id, batch_id);
|
||||
CREATE INDEX IF NOT EXISTS "index_runner_header_pk" ON "runner_header" (
|
||||
"runner_id"
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "index_runner_header_strat" ON "runner_header" (
|
||||
"strat_id"
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "index_runner_header_batch" ON "runner_header" (
|
||||
"batch_id"
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "index_runner_detail_pk" ON "runner_detail" (
|
||||
"runner_id"
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS "index_runner_logs" ON "runner_logs" (
|
||||
"runner_id",
|
||||
"time"
|
||||
);
|
||||
INSERT INTO config_table VALUES (1, "test", "{}", "json");
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user