finalni instant indikatory + save do arch
This commit is contained in:
@ -1,19 +1,32 @@
|
|||||||
|
|
||||||
|
|
||||||
import v2realbot.controller.services as cs
|
import v2realbot.controller.services as cs
|
||||||
|
from v2realbot.common.model import RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem, InstantIndicator
|
||||||
#[stratvars.indicators.vwma]
|
#[stratvars.indicators.vwma]
|
||||||
runner_id = "b44d6d8f-b44d-45b1-ad7a-7ee8b0facead"
|
runner_id = "1ac42f29-b902-44df-9bd6-e2a430989705"
|
||||||
toml = """
|
toml = """
|
||||||
type = "custom"
|
#[stratvars.indicators.cross]
|
||||||
subtype = "vwma"
|
type = 'custom'
|
||||||
on_confirmed_only = true
|
subtype = 'conditional'
|
||||||
cp.source = "vwap"
|
on_confirmed_only = true
|
||||||
cp.ref_source = "volume"
|
[cp.conditions.crossdown]
|
||||||
cp.lookback = 50
|
vwap.change_val_if_crossed_down = 'emaSlow'
|
||||||
|
true_val = -1
|
||||||
|
[cp.conditions.crossup]
|
||||||
|
vwap.change_val_if_crossed_up = 'emaSlow'
|
||||||
|
true_val = 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
res, vals = cs.preview_indicator_byTOML(id=runner_id, toml=toml)
|
toml = """
|
||||||
|
#[stratvars.indicators.rsi14]
|
||||||
|
type = 'RSI'
|
||||||
|
source = 'vwap'
|
||||||
|
length = 14
|
||||||
|
on_confirmed_only = true
|
||||||
|
"""
|
||||||
|
indicator = InstantIndicator(name="rsi14alt", toml=toml)
|
||||||
|
|
||||||
|
res, vals = cs.preview_indicator_byTOML(id=runner_id, indicator=indicator)
|
||||||
|
|
||||||
print(res)
|
print(res)
|
||||||
print(vals)
|
print(vals)
|
||||||
|
|||||||
@ -86,7 +86,7 @@ if save_new_ind:
|
|||||||
|
|
||||||
sada["indicators"][0]["pred_added"] = ind_pred
|
sada["indicators"][0]["pred_added"] = ind_pred
|
||||||
|
|
||||||
req = update_archive_detail(runner_id, sada)
|
req, res = update_archive_detail(runner_id, sada)
|
||||||
print(f"indicator pred_added was ADDED to {runner_id}")
|
print(f"indicator pred_added was ADDED to {runner_id}")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class ConnectionPool:
|
|||||||
return connection
|
return connection
|
||||||
|
|
||||||
|
|
||||||
def execute_with_retry(cursor: sqlite3.Cursor, statement: str, retry_interval: int = 1) -> sqlite3.Cursor:
|
def execute_with_retry(cursor: sqlite3.Cursor, statement: str, params = None, retry_interval: int = 1) -> sqlite3.Cursor:
|
||||||
"""get connection from pool and execute SQL statement with retry logic if required.
|
"""get connection from pool and execute SQL statement with retry logic if required.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -44,7 +44,10 @@ def execute_with_retry(cursor: sqlite3.Cursor, statement: str, retry_interval: i
|
|||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
return cursor.execute(statement)
|
if params is None:
|
||||||
|
return cursor.execute(statement)
|
||||||
|
else:
|
||||||
|
return cursor.execute(statement, params)
|
||||||
except sqlite3.OperationalError as e:
|
except sqlite3.OperationalError as e:
|
||||||
if str(e) == "database is locked":
|
if str(e) == "database is locked":
|
||||||
print("database retry in 1s." + str(e))
|
print("database retry in 1s." + str(e))
|
||||||
|
|||||||
@ -267,9 +267,9 @@ class RunArchiveDetail(BaseModel):
|
|||||||
trades: List[TradeUpdate]
|
trades: List[TradeUpdate]
|
||||||
ext_data: Optional[dict]
|
ext_data: Optional[dict]
|
||||||
|
|
||||||
class TomlInput(BaseModel):
|
|
||||||
toml: str
|
class InstantIndicator(BaseModel):
|
||||||
# class Trade(BaseModel):
|
name: str
|
||||||
# order: Order
|
toml: str
|
||||||
# value: float
|
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from alpaca.data.enums import DataFeed
|
|||||||
from alpaca.data.timeframe import TimeFrame
|
from alpaca.data.timeframe import TimeFrame
|
||||||
from v2realbot.strategy.base import StrategyState
|
from v2realbot.strategy.base import StrategyState
|
||||||
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide
|
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide
|
||||||
from v2realbot.common.model import RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem
|
from v2realbot.common.model import RunDay, StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveView, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent, TestList, Intervals, ConfigItem, InstantIndicator
|
||||||
from v2realbot.utils.utils import AttributeDict, zoneNY, zonePRG, safe_get, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram
|
from v2realbot.utils.utils import AttributeDict, zoneNY, zonePRG, safe_get, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram
|
||||||
from v2realbot.utils.ilog import delete_logs
|
from v2realbot.utils.ilog import delete_logs
|
||||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||||
@ -32,6 +32,8 @@ from threading import Lock
|
|||||||
from v2realbot.common.db import pool, execute_with_retry, row_to_runarchive, row_to_runarchiveview
|
from v2realbot.common.db import pool, execute_with_retry, row_to_runarchive, row_to_runarchiveview
|
||||||
from sqlite3 import OperationalError, Row
|
from sqlite3 import OperationalError, Row
|
||||||
import v2realbot.strategyblocks.indicators.custom as ci
|
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.interfaces.backtest_interface import BacktestInterface
|
from v2realbot.interfaces.backtest_interface import BacktestInterface
|
||||||
|
|
||||||
#from pyinstrument import Profiler
|
#from pyinstrument import Profiler
|
||||||
@ -1071,12 +1073,15 @@ def update_archive_detail(id: UUID, archdetail: RunArchiveDetail):
|
|||||||
try:
|
try:
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
json_string = json.dumps(archdetail, default=json_serial)
|
json_string = json.dumps(archdetail, default=json_serial)
|
||||||
statement = f"UPDATE runner_detail SET data = '{json_string}' WHERE runner_id='{str(id)}'"
|
statement = "UPDATE runner_detail SET data = ? WHERE runner_id = ?"
|
||||||
res = execute_with_retry(c,statement)
|
params = (json_string, str(id))
|
||||||
|
##statement = f"UPDATE runner_detail SET data = '{json_string}' WHERE runner_id='{str(id)}'"
|
||||||
|
##print(statement)
|
||||||
|
res = execute_with_retry(cursor=c,statement=statement,params=params)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
finally:
|
finally:
|
||||||
pool.release_connection(conn)
|
pool.release_connection(conn)
|
||||||
return res.rowcount
|
return 0, res.rowcount
|
||||||
|
|
||||||
def insert_archive_detail(archdetail: RunArchiveDetail):
|
def insert_archive_detail(archdetail: RunArchiveDetail):
|
||||||
conn = pool.get_connection()
|
conn = pool.get_connection()
|
||||||
@ -1111,15 +1116,40 @@ def get_testlists():
|
|||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
#WIP - possibility to add TOML indicator
|
#WIP - instant indicators
|
||||||
# open issues: hodnoty dalsich indikatoru
|
def preview_indicator_byTOML(id: UUID, indicator: InstantIndicator):
|
||||||
def preview_indicator_byTOML(id: UUID, toml: str):
|
|
||||||
try:
|
try:
|
||||||
res, toml_parsed = parse_toml_string(toml)
|
if indicator.name is None:
|
||||||
|
return (-2, "name is required")
|
||||||
|
|
||||||
|
#print("na zacatku", indicator.toml)
|
||||||
|
|
||||||
|
tomlino = indicator.toml
|
||||||
|
jmeno = indicator.name
|
||||||
|
#print("tomlino",tomlino)
|
||||||
|
#print("jmeno",jmeno)
|
||||||
|
|
||||||
|
# indicator = AttributeDict(**indicator.__dict__)
|
||||||
|
|
||||||
|
|
||||||
|
# print(indicator)
|
||||||
|
# def format_toml_string(toml_string):
|
||||||
|
# return f"'''{toml_string.strip()}'''"
|
||||||
|
# print("before",indicator['toml'])
|
||||||
|
# indicator['toml'] = format_toml_string(indicator['toml'])
|
||||||
|
# print(indicator['toml'])
|
||||||
|
|
||||||
|
# print("jmeno", str(indicator.name))
|
||||||
|
# row = f"[stratvars]\n[stratvars.indicators.{str(indicator.name)}]\n"
|
||||||
|
# print(row, end='')
|
||||||
|
# row = "[stratvars]\n[stratvars.indicators.{indicator.name}]\n"
|
||||||
|
# print(row.format(indicator=indicator))
|
||||||
|
# print(row)
|
||||||
|
res, toml_parsed = parse_toml_string(tomlino)
|
||||||
if res < 0:
|
if res < 0:
|
||||||
return (-2, "toml invalid")
|
return (-2, "toml invalid")
|
||||||
|
|
||||||
print("parsed toml", toml_parsed)
|
#print("parsed toml", toml_parsed)
|
||||||
|
|
||||||
subtype = safe_get(toml_parsed, 'subtype', False)
|
subtype = safe_get(toml_parsed, 'subtype', False)
|
||||||
if subtype is None:
|
if subtype is None:
|
||||||
@ -1133,16 +1163,6 @@ def preview_indicator_byTOML(id: UUID, toml: str):
|
|||||||
if res < 0:
|
if res < 0:
|
||||||
return (-2, "no archived runner {id}")
|
return (-2, "no archived runner {id}")
|
||||||
|
|
||||||
# class RunArchiveDetail(BaseModel):
|
|
||||||
# id: UUID
|
|
||||||
# name: str
|
|
||||||
# bars: dict
|
|
||||||
# #trades: Optional[dict]
|
|
||||||
# indicators: List[dict]
|
|
||||||
# statinds: dict
|
|
||||||
# trades: List[TradeUpdate]
|
|
||||||
# ext_data: Optional[dict]
|
|
||||||
|
|
||||||
#TODO - conditional udelat podminku
|
#TODO - conditional udelat podminku
|
||||||
# if value == "conditional":
|
# if value == "conditional":
|
||||||
# conditions = state.vars.indicators[indname]["cp"]["conditions"]
|
# conditions = state.vars.indicators[indname]["cp"]["conditions"]
|
||||||
@ -1156,57 +1176,140 @@ def preview_indicator_byTOML(id: UUID, toml: str):
|
|||||||
detail = RunArchiveDetail(**val)
|
detail = RunArchiveDetail(**val)
|
||||||
#print("toto jsme si dotahnuli", detail.bars)
|
#print("toto jsme si dotahnuli", detail.bars)
|
||||||
|
|
||||||
|
#pokud tento indikator jiz je v detailu, tak ho odmazeme
|
||||||
|
if indicator.name in detail.indicators[0]:
|
||||||
|
del detail.indicators[0][indicator.name]
|
||||||
|
|
||||||
|
|
||||||
#new dicts
|
#new dicts
|
||||||
new_bars = {key: [] for key in detail.bars.keys()}
|
new_bars = {key: [] for key in detail.bars.keys()}
|
||||||
new_bars = AttributeDict(**new_bars)
|
new_bars = AttributeDict(**new_bars)
|
||||||
|
new_data = {key: None for key in detail.bars.keys()}
|
||||||
|
new_data= AttributeDict(**new_data)
|
||||||
new_inds = {key: [] for key in detail.indicators[0].keys()}
|
new_inds = {key: [] for key in detail.indicators[0].keys()}
|
||||||
new_inds = AttributeDict(**new_inds)
|
new_inds = AttributeDict(**new_inds)
|
||||||
interface = BacktestInterface(symbol="X", bt=None)
|
interface = BacktestInterface(symbol="X", bt=None)
|
||||||
|
|
||||||
state = StrategyState(name="XX", symbol = "X", stratvars = toml, interface=interface)
|
##dame nastaveni indikatoru do tvaru, ktery stratvars ocekava (pro dynmaicke inicializace)
|
||||||
|
stratvars = AttributeDict(indicators=AttributeDict(**{jmeno:toml_parsed}))
|
||||||
|
print("stratvars", stratvars)
|
||||||
|
|
||||||
|
state = StrategyState(name="XX", symbol = "X", stratvars = AttributeDict(**stratvars), interface=interface)
|
||||||
|
|
||||||
|
#inicializujeme novy indikator v cilovem dict a stavovem inds.
|
||||||
|
new_inds[indicator.name] = []
|
||||||
|
new_inds[indicator.name] = []
|
||||||
|
|
||||||
state.bars = new_bars
|
state.bars = new_bars
|
||||||
state.indicators = new_inds
|
state.indicators = new_inds
|
||||||
|
|
||||||
new_inds["new"] = []
|
|
||||||
print("delka",len(detail.bars["close"]))
|
print("delka",len(detail.bars["close"]))
|
||||||
|
|
||||||
#intitialize indicator mapping - in order to use eval in expression
|
#intitialize indicator mapping - in order to use eval in expression
|
||||||
local_dict_inds = {key: state.indicators[key] for key in state.indicators.keys() if key != "time"}
|
local_dict_inds = {key: state.indicators[key] for key in state.indicators.keys() if key != "time"}
|
||||||
local_dict_bars = {key: state.bars[key] for key in state.bars.keys() if key != "time"}
|
local_dict_bars = {key: state.bars[key] for key in state.bars.keys() if key != "time"}
|
||||||
|
|
||||||
state.ind_mapping = {**local_dict_inds, **local_dict_bars}
|
state.ind_mapping = {**local_dict_inds, **local_dict_bars}
|
||||||
print("IND MAPPING DONE:", state.ind_mapping)
|
print("IND MAPPING DONE:", state.ind_mapping)
|
||||||
|
|
||||||
|
##intialize dynamic indicators
|
||||||
|
initialize_dynamic_indicators(state)
|
||||||
|
|
||||||
|
|
||||||
|
# print("subtype")
|
||||||
|
# function = "ci."+subtype+"."+subtype
|
||||||
|
# print("funkce", function)
|
||||||
|
# custom_function = eval(function)
|
||||||
|
|
||||||
print("subtype")
|
|
||||||
function = "ci."+subtype+"."+subtype
|
|
||||||
print("funkce", function)
|
|
||||||
custom_function = eval(function)
|
|
||||||
#iterujeme nad bary a on the fly pridavame novou hodnotu do vsech indikatoru a nakonec nad tim spustime indikator
|
#iterujeme nad bary a on the fly pridavame novou hodnotu do vsech indikatoru a nakonec nad tim spustime indikator
|
||||||
#tak muzeme v toml pouzit i hodnoty ostatnich indikatoru
|
#tak muzeme v toml pouzit i hodnoty ostatnich indikatoru
|
||||||
for i in range(len(detail.bars["close"])):
|
for i in range(len(detail.bars["close"])):
|
||||||
for key in detail.bars:
|
for key in detail.bars:
|
||||||
state.bars[key].append(detail.bars[key][i])
|
state.bars[key].append(detail.bars[key][i])
|
||||||
|
#naplnime i data aktualne
|
||||||
|
new_data[key] = state.bars[key][-1]
|
||||||
for key in detail.indicators[0]:
|
for key in detail.indicators[0]:
|
||||||
state.indicators[key].append(detail.indicators[0][key][i])
|
state.indicators[key].append(detail.indicators[0][key][i])
|
||||||
|
|
||||||
new_inds["new"].append(0)
|
new_inds[indicator.name].append(0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res_code, new_val = custom_function(state, custom_params)
|
populate_dynamic_indicators(new_data, state)
|
||||||
if res_code == 0:
|
# res_code, new_val = custom_function(state, custom_params)
|
||||||
new_inds["new"][-1]=new_val
|
# if res_code == 0:
|
||||||
|
# new_inds[indicator.name][-1]=new_val
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(str(e) + format_exc())
|
print(str(e) + format_exc())
|
||||||
|
|
||||||
print("Done", f"delka {len(new_inds['new'])}", new_inds["new"])
|
|
||||||
|
|
||||||
return 0, new_inds["new"]
|
print("Done - static", f"delka {len(state.indicators[indicator.name])}", state.indicators[indicator.name])
|
||||||
|
#print("Done", f"delka {len(new_inds[indicator.name])}", new_inds[indicator.name])
|
||||||
|
|
||||||
|
new_inds[indicator.name] = state.indicators[indicator.name]
|
||||||
|
|
||||||
|
#ukládáme do ArchRunneru
|
||||||
|
detail.indicators[0][indicator.name] = new_inds[indicator.name]
|
||||||
|
|
||||||
|
#do ext dat ukladame jmeno indikatoru (podle toho oznacuje jako zmenene)
|
||||||
|
|
||||||
|
#inicializace ext_data a instantindicator pokud neexistuje
|
||||||
|
if hasattr(detail, "ext_data"):
|
||||||
|
if "instantindicators" not in detail.ext_data:
|
||||||
|
detail.ext_data["instantindicators"] = []
|
||||||
|
else:
|
||||||
|
setattr(detail, "ext_data", dict(instantindicators=[]))
|
||||||
|
|
||||||
|
#pokud tam je tak odebereme
|
||||||
|
for ind in detail.ext_data["instantindicators"]:
|
||||||
|
if ind["name"] == indicator.name:
|
||||||
|
detail.ext_data["instantindicators"].remove(ind)
|
||||||
|
print("removed old from EXT_DATA")
|
||||||
|
|
||||||
|
#a pridame aktualni
|
||||||
|
detail.ext_data["instantindicators"].append(indicator)
|
||||||
|
print("added to EXT_DATA")
|
||||||
|
#updatneme ArchRunner
|
||||||
|
res, val = update_archive_detail(id, detail)
|
||||||
|
if res == 0:
|
||||||
|
print(f"arch runner {id} updated")
|
||||||
|
|
||||||
|
return 0, new_inds[indicator.name]
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(str(e) + format_exc())
|
print(str(e) + format_exc())
|
||||||
return -2, str(e)
|
return -2, str(e)
|
||||||
|
|
||||||
|
def delete_indicator_byName(id: UUID, indicator: InstantIndicator):
|
||||||
|
try:
|
||||||
|
#dotahne runner details
|
||||||
|
res, val = get_archived_runner_details_byID(id)
|
||||||
|
if res < 0:
|
||||||
|
return (-2, "no archived runner {id}")
|
||||||
|
|
||||||
|
detail = RunArchiveDetail(**val)
|
||||||
|
#print("toto jsme si dotahnuli", detail.bars)
|
||||||
|
|
||||||
|
#pokud tento indikator je v detailu
|
||||||
|
if indicator.name in detail.indicators[0]:
|
||||||
|
del detail.indicators[0][indicator.name]
|
||||||
|
print("values removed from indicators")
|
||||||
|
|
||||||
|
#do ext dat ukladame jmeno indikatoru (podle toho oznacuje jako zmenene)
|
||||||
|
if hasattr(detail, "ext_data") and "instantindicators" in detail.ext_data:
|
||||||
|
for ind in detail.ext_data["instantindicators"]:
|
||||||
|
if ind["name"] == indicator.name:
|
||||||
|
detail.ext_data["instantindicators"].remove(ind)
|
||||||
|
print("removed from EXT_DATA")
|
||||||
|
|
||||||
|
#updatneme ArchRunner
|
||||||
|
res, val = update_archive_detail(id, detail)
|
||||||
|
if res == 0:
|
||||||
|
print("Archive udpated")
|
||||||
|
|
||||||
|
return 0, val
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e) + format_exc())
|
||||||
|
return -2, str(e)
|
||||||
|
|
||||||
# region CONFIG db services
|
# region CONFIG db services
|
||||||
#TODO vytvorit modul pro dotahovani z pythonu (get_from_config(var_name, def_value) {)- stejne jako v js
|
#TODO vytvorit modul pro dotahovani z pythonu (get_from_config(var_name, def_value) {)- stejne jako v js
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import uvicorn
|
|||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
import v2realbot.controller.services as cs
|
import v2realbot.controller.services as cs
|
||||||
from v2realbot.utils.ilog import get_log_window
|
from v2realbot.utils.ilog import get_log_window
|
||||||
from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade, RunArchive, RunArchiveView, RunArchiveDetail, Bar, RunArchiveChange, TestList, ConfigItem, TomlInput
|
from v2realbot.common.model import StrategyInstance, RunnerView, RunRequest, Trade, RunArchive, RunArchiveView, RunArchiveDetail, Bar, RunArchiveChange, TestList, ConfigItem, InstantIndicator
|
||||||
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, WebSocketException, Cookie, Query
|
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, WebSocketException, Cookie, Query
|
||||||
from fastapi.responses import FileResponse
|
from fastapi.responses import FileResponse
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
@ -432,15 +432,27 @@ def _delete_archived_runners_byIDs(runner_ids: list[UUID]):
|
|||||||
#WIP - TOM indicator preview from frontend
|
#WIP - TOM indicator preview from frontend
|
||||||
#return indicator value for archived runner
|
#return indicator value for archived runner
|
||||||
@app.put("/archived_runners/{runner_id}/previewindicator", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK)
|
@app.put("/archived_runners/{runner_id}/previewindicator", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK)
|
||||||
def _preview_indicator_byTOML(runner_id: UUID, toml: TomlInput) -> list[float]:
|
def _preview_indicator_byTOML(runner_id: UUID, indicator: InstantIndicator) -> list[float]:
|
||||||
#mozna pak pridat name
|
#mozna pak pridat name
|
||||||
res, vals = cs.preview_indicator_byTOML(id=runner_id, toml=toml.toml)
|
res, vals = cs.preview_indicator_byTOML(id=runner_id, indicator=indicator)
|
||||||
if res == 0: return vals
|
if res == 0: return vals
|
||||||
elif res == -1:
|
elif res == -1:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{vals}")
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{vals}")
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error not changed: {res}:{runner_id}:{vals}")
|
raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error not changed: {res}:{runner_id}:{vals}")
|
||||||
|
|
||||||
|
#delete instant indicator from detail
|
||||||
|
@app.delete("/archived_runners/{runner_id}/previewindicator", dependencies=[Depends(api_key_auth)], status_code=status.HTTP_200_OK)
|
||||||
|
def _delete_indicator_byName(runner_id: UUID, indicator: InstantIndicator):
|
||||||
|
#mozna pak pridat name
|
||||||
|
res, vals = cs.delete_indicator_byName(id=runner_id, indicator=indicator)
|
||||||
|
if res == 0: return vals
|
||||||
|
elif res == -1:
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error: {res}:{vals}")
|
||||||
|
else:
|
||||||
|
raise HTTPException(status_code=status.HTTP_406_NOT_ACCEPTABLE, detail=f"Error not changed: {res}:{runner_id}:{vals}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#edit archived runner ("note",..)
|
#edit archived runner ("note",..)
|
||||||
@app.patch("/archived_runners/{runner_id}", dependencies=[Depends(api_key_auth)])
|
@app.patch("/archived_runners/{runner_id}", dependencies=[Depends(api_key_auth)])
|
||||||
|
|||||||
@ -747,6 +747,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<script src="/static/js/utils.js"></script>
|
<script src="/static/js/utils.js"></script>
|
||||||
|
<script src="/static/js/instantindicators.js"></script>
|
||||||
<script src="/static/js/archivechart.js"></script>
|
<script src="/static/js/archivechart.js"></script>
|
||||||
<script src="/static/js/archivetables.js"></script>
|
<script src="/static/js/archivetables.js"></script>
|
||||||
<script src="/static/js/livewebsocket.js"></script>
|
<script src="/static/js/livewebsocket.js"></script>
|
||||||
|
|||||||
@ -340,26 +340,45 @@ function chart_indicators(data, visible, offset) {
|
|||||||
var cnf = null
|
var cnf = null
|
||||||
//pokud je v nastaveni scale, pouzijeme tu
|
//pokud je v nastaveni scale, pouzijeme tu
|
||||||
var scale = null
|
var scale = null
|
||||||
try {
|
var instant = null
|
||||||
if (addedInds[key]) {
|
//console.log(key)
|
||||||
cnf = addedInds[key]
|
//zkusime zda nejde o instantni indikator z arch runneru
|
||||||
scale = TOML.parse(cnf).scale
|
if ((data.ext_data !== null) && (data.ext_data.instantindicators)) {
|
||||||
}
|
let instantIndicator = data.ext_data.instantindicators.find(indicator => indicator.name == key);
|
||||||
else
|
//console.log("nalezen", key)
|
||||||
{
|
if (instantIndicator) {
|
||||||
cnf = "#[stratvars.indicators."+key+"]"+TOML.stringify(stratvars_toml.stratvars.indicators[key], {newline: '\n'})
|
cnf = instantIndicator.toml
|
||||||
scale = stratvars_toml.stratvars.indicators[key].scale
|
scale = TOML.parse(cnf).scale
|
||||||
//cnf = TOML.stringify(stratvars_toml.stratvars.indicators[key], {newline: '\n'})
|
instant = 1
|
||||||
//a = TOML.parse(cnf)
|
|
||||||
//console.log("PARSED again",a)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
//pokud nenalezeno, pak bereme standard
|
||||||
//nic
|
//pozor ted nebereme z addedInds
|
||||||
}
|
if (!cnf) {
|
||||||
|
if (stratvars_toml.stratvars.indicators[key]) {
|
||||||
|
cnf = "#[stratvars.indicators."+key+"]"+TOML.stringify(stratvars_toml.stratvars.indicators[key], {newline: '\n'})
|
||||||
|
scale = stratvars_toml.stratvars.indicators[key].scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// //kontriolujeme v addedInds
|
||||||
|
// if (addedInds[key]) {
|
||||||
|
// cnf = addedInds[key]
|
||||||
|
// scale = TOML.parse(cnf).scale
|
||||||
|
// instant = 1
|
||||||
|
// }
|
||||||
|
// //a az potom bereme normos
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// cnf = "#[stratvars.indicators."+key+"]"+TOML.stringify(stratvars_toml.stratvars.indicators[key], {newline: '\n'})
|
||||||
|
// scale = stratvars_toml.stratvars.indicators[key].scale
|
||||||
|
// //cnf = TOML.stringify(stratvars_toml.stratvars.indicators[key], {newline: '\n'})
|
||||||
|
// //a = TOML.parse(cnf)
|
||||||
|
// //console.log("PARSED again",a)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
//initialize indicator and store reference to array
|
//initialize indicator and store reference to array
|
||||||
var obj = {name: key, series: null, cnf:cnf, added: ((addedInds[key])?1:null)}
|
var obj = {name: key, series: null, cnf:cnf, instant: instant}
|
||||||
|
|
||||||
//start
|
//start
|
||||||
//console.log(key)
|
//console.log(key)
|
||||||
@ -580,7 +599,9 @@ function remove_indicators() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//switch to interval pomocna funkce
|
//switch to interval pomocna funkce
|
||||||
function switch_to_interval(interval, data) {
|
function switch_to_interval(interval, data, extra) {
|
||||||
|
store_activated_buttons_state(extra);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
window.alert("no data switch to interval")
|
window.alert("no data switch to interval")
|
||||||
}
|
}
|
||||||
@ -671,7 +692,7 @@ function display_buy_markers(data) {
|
|||||||
//xx - ted bude slLine pole
|
//xx - ted bude slLine pole
|
||||||
transformed_data["sl_line"].forEach((slRecord, index, array) => {
|
transformed_data["sl_line"].forEach((slRecord, index, array) => {
|
||||||
|
|
||||||
console.log("uvnitr")
|
//console.log("uvnitr")
|
||||||
slLine_temp = chart.addLineSeries({
|
slLine_temp = chart.addLineSeries({
|
||||||
// title: "avgpbuyline",
|
// title: "avgpbuyline",
|
||||||
color: '#e4c76d',
|
color: '#e4c76d',
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
let editor_diff_arch1
|
let editor_diff_arch1
|
||||||
let editor_diff_arch2
|
let editor_diff_arch2
|
||||||
var archData = null
|
var archData = null
|
||||||
var addedInds = {}
|
|
||||||
|
|
||||||
function refresh_arch_and_callback(row, callback) {
|
function refresh_arch_and_callback(row, callback) {
|
||||||
//console.log("entering refresh")
|
//console.log("entering refresh")
|
||||||
@ -314,129 +313,6 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//Kod pro add indicator -dat do arch chart souboru
|
|
||||||
|
|
||||||
//modal - delete indicator button
|
|
||||||
$('#deleteIndicatorButton').click(function () {
|
|
||||||
window.$('#indicatorModal').modal('hide');
|
|
||||||
indname = $('#indicatorName').val()
|
|
||||||
//updatneme globalni promennou obsahujici vsechny arch data
|
|
||||||
//TBD nebude fungovat az budu mit vic chartů otevřených - předělat
|
|
||||||
if (archData.indicators[0][indname]) {
|
|
||||||
delete archData.indicators[0][indname]
|
|
||||||
delete addedInds[indname]
|
|
||||||
//get active resolution
|
|
||||||
const element = document.querySelector('.switcher-active-item');
|
|
||||||
resolution = element.textContent
|
|
||||||
//console.log("aktivni rozliseni", resolution)
|
|
||||||
switch_to_interval(resolution, archData)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var myModalEl = document.getElementById('indicatorModal')
|
|
||||||
myModalEl.addEventListener('hidden.bs.modal', function (event) {
|
|
||||||
close_addind_modal()
|
|
||||||
})
|
|
||||||
|
|
||||||
function close_addind_modal() {
|
|
||||||
index = $('#indicatorId').val()
|
|
||||||
const elem = document.getElementById("IND"+index);
|
|
||||||
if (elem) {
|
|
||||||
elem.classList.replace('switcher-item-highlighted', 'switcher-item');
|
|
||||||
}
|
|
||||||
//vracime pripadny schovany del button
|
|
||||||
$('#deleteIndicatorButton').show();
|
|
||||||
window.$('#indicatorModal').modal('hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
//HLAVNI SAVE akce INDICATOR MODAL - ulozi nebo vytvori novy
|
|
||||||
$('#saveIndicatorButton').click(function () {
|
|
||||||
indName = $('#indicatorName').val()
|
|
||||||
if (!indName) {
|
|
||||||
alert("name musi byt vyplneno")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
index = $('#indicatorId').val()
|
|
||||||
var elem = document.getElementById("IND"+index);
|
|
||||||
if (elem) {
|
|
||||||
//pokud existuje - pak jde bud o edit nebo duplicate - podle jmena
|
|
||||||
|
|
||||||
//jmeno je updatnute, jde o duplicate - vytvarime novy index
|
|
||||||
if (elem.textContent !== $('#indicatorName').val()) {
|
|
||||||
//alert("duplikujeme")
|
|
||||||
index_ind++
|
|
||||||
index = index_ind
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//pokud neexistuje, pak jde o novy index - pouzijeme tento
|
|
||||||
|
|
||||||
runner_id = $("#statusArchId").text()
|
|
||||||
if (!runner_id) {
|
|
||||||
alert("no arch runner selected")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// row = archiveRecords.row('.selected').data();
|
|
||||||
// if (row == undefined) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
store_activated_buttons_state()
|
|
||||||
//pridame jeste tu aktualni, aby se zobrazila jako aktivni
|
|
||||||
activatedButtons.push(indName);
|
|
||||||
|
|
||||||
|
|
||||||
//console.log(activatedButtons)
|
|
||||||
|
|
||||||
obj = new Object()
|
|
||||||
obj.runner_id = runner_id
|
|
||||||
obj.toml = ind_editor.getValue()
|
|
||||||
jsonString = JSON.stringify(obj);
|
|
||||||
//console.log("pred odeslanim",jsonString)
|
|
||||||
//cal rest api
|
|
||||||
$.ajax({
|
|
||||||
url:"/archived_runners/"+runner_id+"/previewindicator",
|
|
||||||
beforeSend: function (xhr) {
|
|
||||||
xhr.setRequestHeader('X-API-Key',
|
|
||||||
API_KEY); },
|
|
||||||
method:"PUT",
|
|
||||||
contentType: "application/json",
|
|
||||||
data: jsonString,
|
|
||||||
success:function(data){
|
|
||||||
//kod pro update/vytvoreni je zde stejny - updatujeme jen zdrojove dictionary
|
|
||||||
window.$('#indicatorModal').modal('hide');
|
|
||||||
//console.log(data)
|
|
||||||
//indName = $('#indicatorName').val()
|
|
||||||
//updatneme/vytvorime klic v globalni promennou obsahujici vsechny arch data
|
|
||||||
//TBD nebude fungovat az budu mit vic chartů otevřených - předělat
|
|
||||||
archData.indicators[0][indName] = data
|
|
||||||
|
|
||||||
//glob promenna obsahujici aktualne pridane indikatory a jejich konfigurace
|
|
||||||
addedInds[indName] = obj.toml
|
|
||||||
//get active resolution
|
|
||||||
const element = document.querySelector('.switcher-active-item');
|
|
||||||
resolution = element.textContent
|
|
||||||
//console.log("aktivni rozliseni", resolution)
|
|
||||||
switch_to_interval(resolution, archData)
|
|
||||||
},
|
|
||||||
error: function(xhr, status, error) {
|
|
||||||
var err = eval("(" + xhr.responseText + ")");
|
|
||||||
window.alert(JSON.stringify(xhr));
|
|
||||||
//console.log(JSON.stringify(xhr));
|
|
||||||
//$('#button_runagain_arch').attr('disabled',false);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// #indicatorId
|
|
||||||
// #indicatorName
|
|
||||||
// #indicatorTOML
|
|
||||||
|
|
||||||
|
|
||||||
//$('#editidarchive').val(row.id);
|
|
||||||
//$('#editnote').val(row.note);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//show button
|
//show button
|
||||||
$('#button_show_arch').click(function () {
|
$('#button_show_arch').click(function () {
|
||||||
|
|
||||||
|
|||||||
184
v2realbot/static/js/instantindicators.js
Normal file
184
v2realbot/static/js/instantindicators.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
//docasne ulozeni aktivovanych buttonu pred reloadem
|
||||||
|
var activatedButtons = []
|
||||||
|
//seznam upravenych instant indikatoru a jejich konfigurace
|
||||||
|
// var addedInds = {}
|
||||||
|
|
||||||
|
function store_activated_buttons_state(extra) {
|
||||||
|
activatedButtons = []
|
||||||
|
if (extra) {
|
||||||
|
activatedButtons.push(extra)
|
||||||
|
}
|
||||||
|
//ulozime si stav aktivovaných buttonků před změnou - mozna do sluzby
|
||||||
|
$('#indicatorsButtons .switcher-active-item').each(function() {
|
||||||
|
activatedButtons.push($(this).text());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//JQUERY SECTION
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
//modal - delete indicator button
|
||||||
|
$('#deleteIndicatorButton').click(function () {
|
||||||
|
indname = $('#indicatorName').val()
|
||||||
|
runner_id = $("#statusArchId").text()
|
||||||
|
if (!runner_id) {
|
||||||
|
alert("no arch runner selected")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = new Object()
|
||||||
|
obj.runner_id = runner_id
|
||||||
|
obj.toml = TOML.parse(ind_editor.getValue())
|
||||||
|
obj.name = indname
|
||||||
|
jsonString = JSON.stringify(obj);
|
||||||
|
//console.log("pred odeslanim",jsonString)
|
||||||
|
//cal rest api
|
||||||
|
$.ajax({
|
||||||
|
url:"/archived_runners/"+runner_id+"/previewindicator",
|
||||||
|
beforeSend: function (xhr) {
|
||||||
|
xhr.setRequestHeader('X-API-Key',
|
||||||
|
API_KEY); },
|
||||||
|
method:"DELETE",
|
||||||
|
contentType: "application/json",
|
||||||
|
data: jsonString,
|
||||||
|
success:function(data){
|
||||||
|
window.$('#indicatorModal').modal('hide');
|
||||||
|
//updatneme globalni promennou obsahujici vsechny arch data
|
||||||
|
//TBD nebude fungovat az budu mit vic chartů otevřených - předělat
|
||||||
|
//smazeme zaznam o indiaktoru v lokalni kopii ext_data (z nich se pak prekresli indikatory)
|
||||||
|
if ((archData.ext_data !== null) && (archData.ext_data.instantindicators)) {
|
||||||
|
let index = archData.ext_data.instantindicators.findIndex(indicator => indicator.name === indname);
|
||||||
|
if (index !== -1) {
|
||||||
|
archData.ext_data.instantindicators.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archData.indicators[0][indname]) {
|
||||||
|
delete archData.indicators[0][indname]
|
||||||
|
//delete addedInds[indname]
|
||||||
|
//get active resolution
|
||||||
|
const element = document.querySelector('.switcher-active-item');
|
||||||
|
resolution = element.textContent
|
||||||
|
//console.log("aktivni rozliseni", resolution)
|
||||||
|
switch_to_interval(resolution, archData)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
var err = eval("(" + xhr.responseText + ")");
|
||||||
|
window.alert(JSON.stringify(xhr));
|
||||||
|
//console.log(JSON.stringify(xhr));
|
||||||
|
//$('#button_runagain_arch').attr('disabled',false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var myModalEl = document.getElementById('indicatorModal')
|
||||||
|
myModalEl.addEventListener('hidden.bs.modal', function (event) {
|
||||||
|
close_indicator_modal()
|
||||||
|
})
|
||||||
|
|
||||||
|
function close_indicator_modal() {
|
||||||
|
index = $('#indicatorId').val()
|
||||||
|
const elem = document.getElementById("IND"+index);
|
||||||
|
if (elem) {
|
||||||
|
elem.classList.replace('switcher-item-highlighted', 'switcher-item');
|
||||||
|
}
|
||||||
|
//vracime pripadny schovany del button
|
||||||
|
$('#deleteIndicatorButton').show();
|
||||||
|
$('#saveIndicatorButton').show();
|
||||||
|
window.$('#indicatorModal').modal('hide');
|
||||||
|
}
|
||||||
|
|
||||||
|
//HLAVNI SAVE akce INDICATOR MODAL - ulozi nebo vytvori novy
|
||||||
|
$('#saveIndicatorButton').click(function () {
|
||||||
|
indName = $('#indicatorName').val()
|
||||||
|
if (!indName) {
|
||||||
|
alert("name musi byt vyplneno")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
index = $('#indicatorId').val()
|
||||||
|
var elem = document.getElementById("IND"+index);
|
||||||
|
if (elem) {
|
||||||
|
//pokud existuje - pak jde bud o edit nebo duplicate - podle jmena
|
||||||
|
|
||||||
|
//jmeno je updatnute, jde o duplicate - vytvarime novy index
|
||||||
|
if (elem.textContent !== $('#indicatorName').val()) {
|
||||||
|
//alert("duplikujeme")
|
||||||
|
index_ind++
|
||||||
|
index = index_ind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//pokud neexistuje, pak jde o novy index - pouzijeme tento
|
||||||
|
|
||||||
|
runner_id = $("#statusArchId").text()
|
||||||
|
if (!runner_id) {
|
||||||
|
alert("no arch runner selected")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// store_activated_buttons_state()
|
||||||
|
// //pridame jeste tu aktualni, aby se zobrazila jako aktivni
|
||||||
|
// activatedButtons.push(indName);
|
||||||
|
console.log(activatedButtons)
|
||||||
|
|
||||||
|
obj = new Object()
|
||||||
|
//obj.runner_id = runner_id
|
||||||
|
obj.name = indName
|
||||||
|
obj.toml = ind_editor.getValue()
|
||||||
|
jsonString = JSON.stringify(obj);
|
||||||
|
//console.log("pred odeslanim",jsonString)
|
||||||
|
//cal rest api
|
||||||
|
$.ajax({
|
||||||
|
url:"/archived_runners/"+runner_id+"/previewindicator",
|
||||||
|
beforeSend: function (xhr) {
|
||||||
|
xhr.setRequestHeader('X-API-Key',
|
||||||
|
API_KEY); },
|
||||||
|
method:"PUT",
|
||||||
|
contentType: "application/json",
|
||||||
|
data: jsonString,
|
||||||
|
success:function(data){
|
||||||
|
//kod pro update/vytvoreni je zde stejny - updatujeme jen zdrojove dictionary
|
||||||
|
window.$('#indicatorModal').modal('hide');
|
||||||
|
//console.log(data)
|
||||||
|
//indName = $('#indicatorName').val()
|
||||||
|
//updatneme/vytvorime klic v globalni promennou obsahujici vsechny arch data
|
||||||
|
//TBD nebude fungovat az budu mit vic chartů otevřených - předělat
|
||||||
|
archData.indicators[0][indName] = data
|
||||||
|
|
||||||
|
//pridame pripadne upatneme v ext_data
|
||||||
|
|
||||||
|
//smazeme zaznam o indiaktoru v lokalni kopii ext_data (z nich se pak prekresli indikatory)
|
||||||
|
if ((archData.ext_data !== null) && (archData.ext_data.instantindicators)) {
|
||||||
|
let index = archData.ext_data.instantindicators.findIndex(indicator => indicator.name === indName);
|
||||||
|
if (index !== -1) {
|
||||||
|
archData.ext_data.instantindicators.splice(index, 1);
|
||||||
|
}
|
||||||
|
archData.ext_data.instantindicators.push(obj)
|
||||||
|
}
|
||||||
|
//neexistuje instantindicators - vytvorime jej a vlozime prvni objekt
|
||||||
|
else if ((archData.ext_data !== null) && (!archData.ext_data.instantindicators)) {
|
||||||
|
//a pridame tamtez novy zaznam
|
||||||
|
archData.ext_data["instantindicators"] =[obj]
|
||||||
|
}
|
||||||
|
|
||||||
|
//glob promenna obsahujici aktualne pridane indikatory a jejich konfigurace
|
||||||
|
//addedInds[indName] = obj.toml
|
||||||
|
//get active resolution
|
||||||
|
const element = document.querySelector('.switcher-active-item');
|
||||||
|
resolution = element.textContent
|
||||||
|
//console.log("aktivni rozliseni", resolution)
|
||||||
|
//vykreslime a pridavame jeste nazev indikatoru, ktery se ma vykreslit do aktivnich
|
||||||
|
switch_to_interval(resolution, archData, indName)
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
var err = eval("(" + xhr.responseText + ")");
|
||||||
|
window.alert(JSON.stringify(xhr));
|
||||||
|
//console.log(JSON.stringify(xhr));
|
||||||
|
//$('#button_runagain_arch').attr('disabled',false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@ -13,7 +13,6 @@ var candlestickSeries = null
|
|||||||
var volumeSeries = null
|
var volumeSeries = null
|
||||||
var vwapSeries = null
|
var vwapSeries = null
|
||||||
var statusBarConfig = JSON.parse(localStorage.getItem("statusBarConfig"));
|
var statusBarConfig = JSON.parse(localStorage.getItem("statusBarConfig"));
|
||||||
var activatedButtons = []
|
|
||||||
if (statusBarConfig == null) {
|
if (statusBarConfig == null) {
|
||||||
statusBarConfig = {}
|
statusBarConfig = {}
|
||||||
}
|
}
|
||||||
@ -58,14 +57,6 @@ var indConfig_default = [ {name: "ema", titlevisible: false, embed: true, displa
|
|||||||
{name: "sec_price", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},]
|
{name: "sec_price", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},]
|
||||||
//console.log(JSON.stringify(indConfig_default, null,null, 2))
|
//console.log(JSON.stringify(indConfig_default, null,null, 2))
|
||||||
|
|
||||||
function store_activated_buttons_state() {
|
|
||||||
activatedButtons = []
|
|
||||||
//ulozime si stav aktivovaných buttonků před změnou - mozna do sluzby
|
|
||||||
$('#indicatorsButtons .switcher-active-item').each(function() {
|
|
||||||
activatedButtons.push($(this).text());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function initialize_statusheader() {
|
function initialize_statusheader() {
|
||||||
|
|
||||||
var rows = 2;
|
var rows = 2;
|
||||||
@ -351,7 +342,7 @@ function create_indicator_button(item, index, def) {
|
|||||||
itemEl.title = item.cnf
|
itemEl.title = item.cnf
|
||||||
itemEl.style.color = item.series.options().color;
|
itemEl.style.color = item.series.options().color;
|
||||||
//pokud jde o pridanou on the fly - vybarvime jinak
|
//pokud jde o pridanou on the fly - vybarvime jinak
|
||||||
if (item.added) {
|
if (item.instant) {
|
||||||
itemEl.style.outline = "solid 1px"
|
itemEl.style.outline = "solid 1px"
|
||||||
}
|
}
|
||||||
itemEl.classList.add('switcher-item');
|
itemEl.classList.add('switcher-item');
|
||||||
@ -411,11 +402,35 @@ function onResetClicked() {
|
|||||||
visible: vis });
|
visible: vis });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
store_activated_buttons_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function generateIndicators(e) {
|
function generateIndicators(e) {
|
||||||
alert("stratvars generated to clipboard from selected indicators")
|
store_activated_buttons_state();
|
||||||
|
|
||||||
|
ind_tom = ""
|
||||||
|
indList.forEach(function (item, index) {
|
||||||
|
if (activatedButtons.includes(item.name)) {
|
||||||
|
console.log(item)
|
||||||
|
ind_tom += "\n[stratvars.indicators."+item.name+"]\n" + item.cnf
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ind_editor) {
|
||||||
|
ind_editor.dispose()
|
||||||
|
}
|
||||||
|
require(["vs/editor/editor.main"], () => {
|
||||||
|
ind_editor = monaco.editor.create(document.getElementById('indicatorTOML_editor'), {
|
||||||
|
value: ind_tom,
|
||||||
|
language: 'toml',
|
||||||
|
theme: 'tomlTheme-dark',
|
||||||
|
automaticLayout: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$('#deleteIndicatorButton').hide();
|
||||||
|
$('#saveIndicatorButton').hide();
|
||||||
|
window.$('#indicatorModal').modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
//editace indikatoru, vcetne vytvoreni noveho
|
//editace indikatoru, vcetne vytvoreni noveho
|
||||||
@ -509,6 +524,7 @@ function populate_indicator_buttons(def) {
|
|||||||
//console.log("activatedButtons", activatedButtons)
|
//console.log("activatedButtons", activatedButtons)
|
||||||
//console.log("obsahuje item.name", activatedButtons.includes(item.name), item.name)
|
//console.log("obsahuje item.name", activatedButtons.includes(item.name), item.name)
|
||||||
//pokud existuje v aktivnich pak
|
//pokud existuje v aktivnich pak
|
||||||
|
//console.log("vytvarime button",item.name,activatedButtons)
|
||||||
if ((activatedButtons) && (activatedButtons.includes(item.name))) {
|
if ((activatedButtons) && (activatedButtons.includes(item.name))) {
|
||||||
active = true
|
active = true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,13 +24,19 @@ def populate_dynamic_RSI_indicator(data, state: StrategyState, name):
|
|||||||
req_source = safe_get(options, 'source', 'vwap')
|
req_source = safe_get(options, 'source', 'vwap')
|
||||||
rsi_length = int(safe_get(options, "length",14))
|
rsi_length = int(safe_get(options, "length",14))
|
||||||
rsi_MA_length = safe_get(options, "MA_length", None)
|
rsi_MA_length = safe_get(options, "MA_length", None)
|
||||||
|
start = safe_get(options, "start","linear") #linear/sharp
|
||||||
|
|
||||||
|
|
||||||
if on_confirmed_only is False or (on_confirmed_only is True and data['confirmed']==1):
|
if on_confirmed_only is False or (on_confirmed_only is True and data['confirmed']==1):
|
||||||
try:
|
try:
|
||||||
#source = state.bars[req_source]
|
#source = state.bars[req_source]
|
||||||
source = get_source_series(state, req_source)
|
source = get_source_series(state, req_source)
|
||||||
#cekame na dostatek dat
|
#cekame na dostatek dat
|
||||||
if len(source) > rsi_length:
|
delka = len(source)
|
||||||
|
if delka > rsi_length or start == "linear":
|
||||||
|
if delka <= rsi_length and start == "linear":
|
||||||
|
rsi_length = delka
|
||||||
|
|
||||||
rsi_res = rsi(source, rsi_length)
|
rsi_res = rsi(source, rsi_length)
|
||||||
rsi_value = round(rsi_res[-1],4)
|
rsi_value = round(rsi_res[-1],4)
|
||||||
state.indicators[name][-1]=rsi_value
|
state.indicators[name][-1]=rsi_value
|
||||||
|
|||||||
@ -54,5 +54,6 @@ def conditional(state, params):
|
|||||||
|
|
||||||
return 0, 0
|
return 0, 0
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
printanyway(str(e)+format_exc())
|
||||||
return -2, str(e)+format_exc()
|
return -2, str(e)+format_exc()
|
||||||
|
|
||||||
|
|||||||
@ -17,17 +17,16 @@ def expression(state: StrategyState, params):
|
|||||||
if operation is None :
|
if operation is None :
|
||||||
return -2, "required param missing"
|
return -2, "required param missing"
|
||||||
|
|
||||||
state.ilog(lvl=1,e=f"BEFORE {funcName} {operation=}", **params)
|
state.ilog(lvl=0,e=f"BEFORE {funcName} {operation=}", **params)
|
||||||
|
|
||||||
#pro zacatek eval
|
#pro zacatek eval
|
||||||
val = eval(operation, {'state': state}, state.ind_mapping)
|
val = eval(operation, {'state': state, 'np': np}, state.ind_mapping)
|
||||||
|
|
||||||
|
|
||||||
if not np.isfinite(val):
|
if not np.isfinite(val):
|
||||||
val = 0
|
val = 0
|
||||||
#val = ne.evaluate(operation, state.ind_mapping)
|
#val = ne.evaluate(operation, state.ind_mapping)
|
||||||
|
|
||||||
state.ilog(lvl=1,e=f"AFTER {funcName} {operation=} res:{val}", **params)
|
state.ilog(lvl=1,e=f"IND {funcName} {operation=} res:{val}", **params)
|
||||||
return 0, val
|
return 0, val
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@ def ma(state, params):
|
|||||||
type = safe_get(params, "type", "ema")
|
type = safe_get(params, "type", "ema")
|
||||||
source = safe_get(params, "source", None)
|
source = safe_get(params, "source", None)
|
||||||
lookback = safe_get(params, "lookback",14)
|
lookback = safe_get(params, "lookback",14)
|
||||||
|
start = safe_get(params, "start","linear") #linear/sharp
|
||||||
|
|
||||||
#lookback muze byt odkaz na indikator, pak berem jeho hodnotu
|
#lookback muze byt odkaz na indikator, pak berem jeho hodnotu
|
||||||
lookback = int(value_or_indicator(state, lookback))
|
lookback = int(value_or_indicator(state, lookback))
|
||||||
@ -23,8 +24,11 @@ def ma(state, params):
|
|||||||
source_series = get_source_series(state, source)
|
source_series = get_source_series(state, source)
|
||||||
|
|
||||||
#pokud je mene elementu, pracujeme s tim co je
|
#pokud je mene elementu, pracujeme s tim co je
|
||||||
if len(source_series) > lookback:
|
akt_pocet = len(source_series)
|
||||||
source_series = source_series[-lookback:]
|
if akt_pocet < lookback and start == "linear":
|
||||||
|
lookback = akt_pocet
|
||||||
|
|
||||||
|
#source_series = source_series[-lookback:]
|
||||||
|
|
||||||
type = "mi."+type
|
type = "mi."+type
|
||||||
ma_function = eval(type)
|
ma_function = eval(type)
|
||||||
|
|||||||
@ -20,6 +20,7 @@ from traceback import format_exc
|
|||||||
|
|
||||||
def initialize_dynamic_indicators(state):
|
def initialize_dynamic_indicators(state):
|
||||||
#pro vsechny indikatory, ktere maji ve svych stratvars TYPE inicializujeme
|
#pro vsechny indikatory, ktere maji ve svych stratvars TYPE inicializujeme
|
||||||
|
##ßprintanyway(state.vars, state)
|
||||||
dict_copy = state.vars.indicators.copy()
|
dict_copy = state.vars.indicators.copy()
|
||||||
for indname, indsettings in dict_copy.items():
|
for indname, indsettings in dict_copy.items():
|
||||||
for option,value in list(indsettings.items()):
|
for option,value in list(indsettings.items()):
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import decimal
|
|||||||
from v2realbot.enums.enums import RecordType, Mode, StartBarAlign
|
from v2realbot.enums.enums import RecordType, Mode, StartBarAlign
|
||||||
import pickle
|
import pickle
|
||||||
import os
|
import os
|
||||||
from v2realbot.common.model import StrategyInstance, Runner, RunArchive, RunArchiveDetail, Intervals, SLHistory
|
from v2realbot.common.model import StrategyInstance, Runner, RunArchive, RunArchiveDetail, Intervals, SLHistory, InstantIndicator
|
||||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||||
from typing import List
|
from typing import List
|
||||||
import tomli
|
import tomli
|
||||||
@ -337,6 +337,7 @@ def json_serial(obj):
|
|||||||
RunArchiveDetail: lambda obj: obj.__dict__,
|
RunArchiveDetail: lambda obj: obj.__dict__,
|
||||||
Intervals: lambda obj: obj.__dict__,
|
Intervals: lambda obj: obj.__dict__,
|
||||||
SLHistory: lambda obj: obj.__dict__,
|
SLHistory: lambda obj: obj.__dict__,
|
||||||
|
InstantIndicator: lambda obj: obj.__dict__,
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer = type_map.get(type(obj))
|
serializer = type_map.get(type(obj))
|
||||||
@ -354,29 +355,9 @@ def json_serial_old(obj):
|
|||||||
|
|
||||||
if isinstance(obj, (datetime, date)):
|
if isinstance(obj, (datetime, date)):
|
||||||
return obj.timestamp()
|
return obj.timestamp()
|
||||||
if isinstance(obj, UUID):
|
if isinstance(obj, UUID) or isinstance(obj, Enum) or isinstance(obj, np.int64):
|
||||||
return str(obj)
|
return str(obj)
|
||||||
if isinstance(obj, Enum):
|
if type(obj) in [Order, TradeUpdate, btOrder, btTradeUpdate, RunArchive, Trade, RunArchiveDetail, Intervals, SLHistory, InstantIndicator]:
|
||||||
return str(obj)
|
|
||||||
if isinstance(obj, np.int64):
|
|
||||||
return int(obj)
|
|
||||||
if type(obj) is Order:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is TradeUpdate:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is btOrder:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is btTradeUpdate:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is RunArchive:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is Trade:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is RunArchiveDetail:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is Intervals:
|
|
||||||
return obj.__dict__
|
|
||||||
if type(obj) is SLHistory:
|
|
||||||
return obj.__dict__
|
return obj.__dict__
|
||||||
|
|
||||||
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
|
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
|
||||||
|
|||||||
Reference in New Issue
Block a user