diff --git a/v2realbot/ENTRY_ClassicSL_v01.py b/v2realbot/ENTRY_ClassicSL_v01.py index bdd7621..ec92942 100644 --- a/v2realbot/ENTRY_ClassicSL_v01.py +++ b/v2realbot/ENTRY_ClassicSL_v01.py @@ -2,7 +2,7 @@ import os,sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from v2realbot.strategy.base import StrategyState from v2realbot.strategy.StrategyOrderLimitVykladaciNormalizedMYSELL import StrategyOrderLimitVykladaciNormalizedMYSELL -from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide, OrderType +from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide, OrderType, Followup from v2realbot.indicators.indicators import ema, natr, roc from v2realbot.indicators.oscillators import rsi from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType @@ -1011,8 +1011,9 @@ def next(data, state: StrategyState): return price2dec(float(state.avgp)+normalized_max_profit,3) if int(state.positions) > 0 else price2dec(float(state.avgp)-normalized_max_profit,3) - - def reverse_conditions_met(direction: TradeDirection): + #otestuje keyword podminky (napr. reverse_if, nebo exitadd_if) + def keyword_conditions_met(direction: TradeDirection, keyword: KW): + action = str(keyword).upper() if direction == TradeDirection.LONG: smer = "long" else: @@ -1022,7 +1023,7 @@ def next(data, state: StrategyState): exit_cond_only_on_confirmed = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) if exit_cond_only_on_confirmed and data['confirmed'] == 0: - state.ilog(lvl=0,e="REVERSAL CHECK COND ONLY ON CONFIRMED BAR") + state.ilog(lvl=0,e=f"{action} CHECK COND ONLY ON CONFIRMED BAR") return False #TOTO zatim u REVERSU neresime @@ -1066,37 +1067,123 @@ def next(data, state: StrategyState): # return False #bereme bud exit condition signalu, ktery activeTrade vygeneroval+ fallback na general - state.ilog(lvl=0,e=f"REVERSE CONDITIONS ENTRY {smer}", conditions=state.vars.conditions[KW.reverse]) + state.ilog(lvl=0,e=f"{action} CONDITIONS ENTRY {smer}", conditions=state.vars.conditions[KW.reverse]) mother_signal = state.vars.activeTrade.generated_by if mother_signal is not None: - cond_dict = state.vars.conditions[KW.reverse][state.vars.activeTrade.generated_by][smer] + cond_dict = state.vars.conditions[keyword][state.vars.activeTrade.generated_by][smer] result, conditions_met = evaluate_directive_conditions(cond_dict, "OR") - state.ilog(lvl=1,e=f"REVERSE CONDITIONS of {mother_signal} =OR= {result}", **conditions_met, cond_dict=cond_dict) + state.ilog(lvl=1,e=f"{action} CONDITIONS of {mother_signal} =OR= {result}", **conditions_met, cond_dict=cond_dict) if result: return True #OR neprosly testujeme AND result, conditions_met = evaluate_directive_conditions(cond_dict, "AND") - state.ilog(lvl=1,e=f"REVERSE CONDITIONS of {mother_signal} =AND= {result}", **conditions_met, cond_dict=cond_dict) + state.ilog(lvl=1,e=f"{action} CONDITIONS of {mother_signal} =AND= {result}", **conditions_met, cond_dict=cond_dict) if result: return True #pokud nemame mother signal nebo exit nevratil nic, fallback na common - cond_dict = state.vars.conditions[KW.reverse]["common"][smer] + cond_dict = state.vars.conditions[keyword]["common"][smer] result, conditions_met = evaluate_directive_conditions(cond_dict, "OR") - state.ilog(lvl=1,e=f"REVERSE CONDITIONS of COMMON =OR= {result}", **conditions_met, cond_dict=cond_dict) + state.ilog(lvl=1,e=f"{action} CONDITIONS of COMMON =OR= {result}", **conditions_met, cond_dict=cond_dict) if result: return True #OR neprosly testujeme AND result, conditions_met = evaluate_directive_conditions(cond_dict, "AND") - state.ilog(lvl=0,e=f"REVERSE CONDITIONS of COMMON =AND= {result}", **conditions_met, cond_dict=cond_dict) + state.ilog(lvl=0,e=f"{action} CONDITIONS of COMMON =AND= {result}", **conditions_met, cond_dict=cond_dict) if result: return True + #DECOMISSIONOVANI - nahrazeno obacnou keyword_conditions_met + # def reverse_conditions_met(direction: TradeDirection): + # if direction == TradeDirection.LONG: + # smer = "long" + # else: + # smer = "short" + + # directive_name = "exit_cond_only_on_confirmed" + # exit_cond_only_on_confirmed = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) + + # if exit_cond_only_on_confirmed and data['confirmed'] == 0: + # state.ilog(lvl=0,e="REVERSAL CHECK COND ONLY ON CONFIRMED BAR") + # return False + + # #TOTO zatim u REVERSU neresime + # # #POKUD je nastaven MIN PROFIT, zkontrolujeme ho a az pripadne pustime CONDITIONY + # # directive_name = "exit_cond_min_profit" + # # exit_cond_min_profit = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, None)) + + # # #máme nastavený exit_cond_min_profit + # # # zjistíme, zda jsme v daném profit a případně nepustíme dál + # # # , zjistíme aktuální cenu a přičteme k avgp tento profit a podle toho pustime dal + + # # if exit_cond_min_profit is not None: + # # exit_cond_min_profit_normalized = normalize_tick(float(exit_cond_min_profit)) + # # exit_cond_goal_price = price2dec(float(state.avgp)+exit_cond_min_profit_normalized,3) if int(state.positions) > 0 else price2dec(float(state.avgp)-exit_cond_min_profit_normalized,3) + # # curr_price = float(data["close"]) + # # state.ilog(lvl=0,e=f"EXIT COND min profit {exit_cond_goal_price=} {exit_cond_min_profit=} {exit_cond_min_profit_normalized=} {curr_price=}") + # # if (int(state.positions) < 0 and curr_price<=exit_cond_goal_price) or (int(state.positions) > 0 and curr_price>=exit_cond_goal_price): + # # state.ilog(lvl=0,e=f"EXIT COND min profit PASS - POKRACUJEME") + # # else: + # # state.ilog(lvl=0,e=f"EXIT COND min profit NOT PASS") + # # return False + + # #TOTO ZATIM NEMA VYZNAM + # # options = safe_get(state.vars, 'exit_conditions', None) + # # if options is None: + # # state.ilog(lvl=0,e="No options for exit conditions in stratvars") + # # return False + + # # disable_exit_proteciton_when = dict(AND=dict(), OR=dict()) + + # # #preconditions + # # disable_exit_proteciton_when['disabled_in_config'] = safe_get(options, 'enabled', False) is False + # # #too good to be true (maximum profit) + # # #disable_sell_proteciton_when['tgtbt_reached'] = safe_get(options, 'tgtbt', False) is False + # # disable_exit_proteciton_when['disable_if_positions_above'] = int(safe_get(options, 'disable_if_positions_above', 0)) < abs(int(state.positions)) + + # # #testing preconditions + # # result, conditions_met = eval_cond_dict(disable_exit_proteciton_when) + # # if result: + # # state.ilog(lvl=0,e=f"EXIT_CONDITION for{smer} DISABLED by {conditions_met}", **conditions_met) + # # return False + + # #bereme bud exit condition signalu, ktery activeTrade vygeneroval+ fallback na general + # state.ilog(lvl=0,e=f"REVERSE CONDITIONS ENTRY {smer}", conditions=state.vars.conditions[KW.reverse]) + + # mother_signal = state.vars.activeTrade.generated_by + + # if mother_signal is not None: + # cond_dict = state.vars.conditions[KW.reverse][state.vars.activeTrade.generated_by][smer] + # result, conditions_met = evaluate_directive_conditions(cond_dict, "OR") + # state.ilog(lvl=1,e=f"REVERSE CONDITIONS of {mother_signal} =OR= {result}", **conditions_met, cond_dict=cond_dict) + # if result: + # return True + + # #OR neprosly testujeme AND + # result, conditions_met = evaluate_directive_conditions(cond_dict, "AND") + # state.ilog(lvl=1,e=f"REVERSE CONDITIONS of {mother_signal} =AND= {result}", **conditions_met, cond_dict=cond_dict) + # if result: + # return True + + + # #pokud nemame mother signal nebo exit nevratil nic, fallback na common + # cond_dict = state.vars.conditions[KW.reverse]["common"][smer] + # result, conditions_met = evaluate_directive_conditions(cond_dict, "OR") + # state.ilog(lvl=1,e=f"REVERSE CONDITIONS of COMMON =OR= {result}", **conditions_met, cond_dict=cond_dict) + # if result: + # return True + + # #OR neprosly testujeme AND + # result, conditions_met = evaluate_directive_conditions(cond_dict, "AND") + # state.ilog(lvl=0,e=f"REVERSE CONDITIONS of COMMON =AND= {result}", **conditions_met, cond_dict=cond_dict) + # if result: + # return True + def exit_conditions_met(direction: TradeDirection): if direction == TradeDirection.LONG: smer = "long" @@ -1276,9 +1363,9 @@ def next(data, state: StrategyState): insert_SL_history() state.ilog(lvl=1,e=f"SL TRAIL GOAL {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized) - def close_position(direction: TradeDirection, reason: str, reverse: bool = False): - reversal_text = "REVERSAL" if reverse else "" - state.ilog(lvl=1,e=f"CLOSING TRADE {reversal_text} {reason} {str(direction)}", curr_price=data["close"], trade=state.vars.activeTrade) + def close_position(direction: TradeDirection, reason: str, followup: Followup = None): + followup_text = str(followup) if followup is not None else "" + state.ilog(lvl=1,e=f"CLOSING TRADE {followup_text} {reason} {str(direction)}", curr_price=data["close"], trade=state.vars.activeTrade) if direction == TradeDirection.SHORT: res = state.buy(size=abs(int(state.positions))) if isinstance(res, int) and res < 0: @@ -1297,8 +1384,8 @@ def next(data, state: StrategyState): state.vars.pending = state.vars.activeTrade.id state.vars.activeTrade = None state.vars.last_exit_index = data["index"] - if reverse: - state.vars.reverse_requested = True + if followup is not None: + state.vars.requested_followup = followup def eval_close_position(): curr_price = float(data['close']) @@ -1324,21 +1411,33 @@ def next(data, state: StrategyState): directive_name = 'reverse_for_SL_exit_short' reverse_for_SL_exit = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) - - close_position(direction=TradeDirection.SHORT, reason="SL REACHED", reverse=reverse_for_SL_exit) + followup_action = Followup.REVERSE if reverse_for_SL_exit else None + close_position(direction=TradeDirection.SHORT, reason="SL REACHED", followup=followup_action) return #REVERSE BASED ON REVERSE CONDITIONS - if reverse_conditions_met(TradeDirection.SHORT): - close_position(direction=TradeDirection.SHORT, reason="REVERSE COND MET", reverse=True) + if keyword_conditions_met(direction=TradeDirection.SHORT, keyword=KW.reverse): + close_position(direction=TradeDirection.SHORT, reason="REVERSE COND MET", followup=Followup.REVERSE) + return + + #EXIT ADD CONDITIONS MET (exit and add) + if keyword_conditions_met(direction=TradeDirection.SHORT, keyword=KW.exitadd): + close_position(direction=TradeDirection.SHORT, reason="EXITADD COND MET", followup=Followup.ADD) return #CLOSING BASED ON EXIT CONDITIONS if exit_conditions_met(TradeDirection.SHORT): directive_name = 'reverse_for_cond_exit_short' - reverse_for_cond_exit = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) - - close_position(direction=TradeDirection.SHORT, reason="EXIT COND MET", reverse=reverse_for_cond_exit) + reverse_for_cond_exit_short = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) + directive_name = 'add_for_cond_exit_short' + add_for_cond_exit_short = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) + if reverse_for_cond_exit_short: + followup_action = Followup.REVERSE + elif add_for_cond_exit_short: + followup_action = Followup.ADD + else: + followup_action = None + close_position(direction=TradeDirection.SHORT, reason="EXIT COND MET", followup=followup_action) return #PROFIT @@ -1359,22 +1458,34 @@ def next(data, state: StrategyState): if curr_price < state.vars.activeTrade.stoploss_value: directive_name = 'reverse_for_SL_exit_long' reverse_for_SL_exit = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) - - close_position(direction=TradeDirection.LONG, reason="SL REACHED", reverse=reverse_for_SL_exit) + followup_action = Followup.REVERSE if reverse_for_SL_exit else None + close_position(direction=TradeDirection.LONG, reason="SL REACHED", followup=followup_action) return #REVERSE BASED ON REVERSE CONDITIONS - if reverse_conditions_met(TradeDirection.LONG): - close_position(direction=TradeDirection.LONG, reason="REVERSE COND MET", reverse=True) + if keyword_conditions_met(TradeDirection.LONG, KW.reverse): + close_position(direction=TradeDirection.LONG, reason="REVERSE COND MET", followup=Followup.REVERSE) + return + + #EXIT ADD CONDITIONS MET (exit and add) + if keyword_conditions_met(TradeDirection.LONG, KW.exitadd): + close_position(direction=TradeDirection.LONG, reason="EXITADD COND MET", followup=Followup.ADD) return #EXIT CONDITIONS if exit_conditions_met(TradeDirection.LONG): directive_name = 'reverse_for_cond_exit_long' - reverse_for_cond_exit = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) - - close_position(direction=TradeDirection.LONG, reason="EXIT CONDS MET", reverse=reverse_for_cond_exit) + reverse_for_cond_exit_long = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) + directive_name = 'add_for_cond_exit_long' + add_for_cond_exit_long = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) + if reverse_for_cond_exit_long: + followup_action = Followup.REVERSE + elif add_for_cond_exit_long: + followup_action = Followup.ADD + else: + followup_action = None + close_position(direction=TradeDirection.LONG, reason="EXIT CONDS MET", followup=followup_action) return #PROFIT @@ -1520,13 +1631,13 @@ def next(data, state: StrategyState): #TESTUJEME GO SIGNAL cond_dict = state.vars.conditions[KW.go][signalname][smer] result, conditions_met = evaluate_directive_conditions(cond_dict, "OR") - state.ilog(lvl=0,e=f"EVAL GO SIGNAL {smer} =OR= {result}", **conditions_met, cond_dict=cond_dict) + state.ilog(lvl=1,e=f"EVAL GO SIGNAL {smer} =OR= {result}", **conditions_met, cond_dict=cond_dict) if result: return True #OR neprosly testujeme AND result, conditions_met = evaluate_directive_conditions(cond_dict, "AND") - state.ilog(lvl=0,e=f"EVAL GO SIGNAL {smer} =AND= {result}", **conditions_met, cond_dict=cond_dict) + state.ilog(lvl=1,e=f"EVAL GO SIGNAL {smer} =AND= {result}", **conditions_met, cond_dict=cond_dict) if result: return True @@ -1598,11 +1709,11 @@ def next(data, state: StrategyState): state.ilog(lvl=1,e=f"PRECOND GENERAL not met {cond_met}", message=cond_met, precond_check=precond_check) return False - state.ilog(lvl=0,e=f"{signalname} ALL PRECOND MET") + state.ilog(lvl=1,e=f"{signalname} ALL PRECOND MET") return True def execute_signal_generator(name): - state.ilog(lvl=1,e=f"SIGNAL SEARCH for {name}", cond_go=state.vars.conditions[KW.go][name], cond_dontgo=state.vars.conditions[KW.dont_go][name], cond_activate=state.vars.conditions[KW.activate][name] ) + state.ilog(lvl=0,e=f"SIGNAL SEARCH for {name}", cond_go=state.vars.conditions[KW.go][name], cond_dontgo=state.vars.conditions[KW.dont_go][name], cond_activate=state.vars.conditions[KW.activate][name] ) options = safe_get(state.vars.signals, name, None) if options is None: @@ -1814,7 +1925,7 @@ def init(state: StrategyState): state.vars.conditions.setdefault(KW.go,{}).setdefault(signalname,{})[smer] = get_conditions_from_configuration(action=KW.go+"_" + smer +"_if", section=section) state.vars.conditions.setdefault(KW.exit,{}).setdefault(signalname,{})[smer] = get_conditions_from_configuration(action=KW.exit+"_" + smer +"_if", section=section) state.vars.conditions.setdefault(KW.reverse,{}).setdefault(signalname,{})[smer] = get_conditions_from_configuration(action=KW.reverse+"_" + smer +"_if", section=section) - + state.vars.conditions.setdefault(KW.exitadd,{}).setdefault(signalname,{})[smer] = get_conditions_from_configuration(action=KW.exitadd+"_" + smer +"_if", section=section) # state.vars.work_dict_dont_do[signalname+"_"+ smer] = get_work_dict_with_directive(starts_with=signalname+"_dont_"+ smer +"_if") # state.vars.work_dict_signal_if[signalname+"_"+ smer] = get_work_dict_with_directive(starts_with=signalname+"_"+smer+"_if") @@ -1823,7 +1934,7 @@ def init(state: StrategyState): for smer in TradeDirection: state.vars.conditions.setdefault(KW.exit,{}).setdefault("common",{})[smer] = get_conditions_from_configuration(action=KW.exit+"_" + smer +"_if", section=section) state.vars.conditions.setdefault(KW.reverse,{}).setdefault("common",{})[smer] = get_conditions_from_configuration(action=KW.reverse+"_" + smer +"_if", section=section) - + state.vars.conditions.setdefault(KW.exitadd,{}).setdefault("common",{})[smer] = get_conditions_from_configuration(action=KW.exitadd+"_" + smer +"_if", section=section) #init klice v extData pro ulozeni historie SL state.extData["sl_history"] = [] @@ -1835,7 +1946,7 @@ def init(state: StrategyState): #obsahuje pripravene Trady ve frontě state.vars.prescribedTrades = [] #flag pro reversal - state.vars.reverse_requested = False + state.vars.requested_followup = None #TODO presunout inicializaci work_dict u podminek - sice hodnoty nepujdou zmenit, ale zlepsi se performance #pripadne udelat refresh kazdych x-iterací diff --git a/v2realbot/__pycache__/config.cpython-310.pyc b/v2realbot/__pycache__/config.cpython-310.pyc index 828af3e..56c196a 100644 Binary files a/v2realbot/__pycache__/config.cpython-310.pyc and b/v2realbot/__pycache__/config.cpython-310.pyc differ diff --git a/v2realbot/config.py b/v2realbot/config.py index f6abb4f..1a22f74 100644 --- a/v2realbot/config.py +++ b/v2realbot/config.py @@ -104,8 +104,13 @@ ACCOUNT2_PAPER_PAPER = True ACCOUNT2_PAPER_FEED = DataFeed.IEX class KW: + activate: str = "activate" dont_go: str = "dont_go" go: str = "go" - activate: str = "activate" + # wip addsize: str = "addsize" exit: str = "exit" - reverse: str = "reverse" \ No newline at end of file + #wip exitsize: str = "exitsize" + exitadd: str = "exitadd" + reverse: str = "reverse" + #exitaddsize: str = "exitaddsize" + diff --git a/v2realbot/enums/__pycache__/enums.cpython-310.pyc b/v2realbot/enums/__pycache__/enums.cpython-310.pyc index d44164a..dfd5fa1 100644 Binary files a/v2realbot/enums/__pycache__/enums.cpython-310.pyc and b/v2realbot/enums/__pycache__/enums.cpython-310.pyc differ diff --git a/v2realbot/enums/enums.py b/v2realbot/enums/enums.py index 805951a..c05ff71 100644 --- a/v2realbot/enums/enums.py +++ b/v2realbot/enums/enums.py @@ -12,6 +12,10 @@ class Order: self.filled_time = filled_time self.limit_price = limit_price +class Followup(str, Enum): + REVERSE = "reverse" + ADD = "add" + class FillCondition(str, Enum): """ Execution settings: diff --git a/v2realbot/main.py b/v2realbot/main.py index f982f87..6b67a55 100644 --- a/v2realbot/main.py +++ b/v2realbot/main.py @@ -27,8 +27,10 @@ from queue import Queue, Empty from threading import Thread import asyncio from v2realbot.common.db import insert_queue, insert_conn, pool -from v2realbot.utils.utils import json_serial +from v2realbot.utils.utils import json_serial, send_to_telegram from uuid import uuid4 +from sqlite3 import OperationalError +from time import sleep #from async io import Queue, QueueEmpty # install() @@ -519,17 +521,25 @@ def insert_queue2db(): # Retrieve data from the queue data = insert_queue.get() - # Unpack the data - runner_id, loglist = data - - c = insert_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) - insert_conn.commit() - # Mark the task as done in the queue + try: + # Unpack the data + runner_id, loglist = data + c = insert_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) + insert_conn.commit() + # Mark the task as done in the queue + except OperationalError as e: + send_to_telegram("insert logs daemon returned" + str(e) + "RETRYING") + if "database is locked" in str(e): + # Database is locked, wait for a while and retry + insert_queue.put(data) # Put the data back into the queue for retry + sleep(1) # You can adjust the sleep duration + else: + raise # If it's another error, raise it #join cekej na dokonceni vsech for i in cs.db.runners: diff --git a/v2realbot/static/js/archivechart.js b/v2realbot/static/js/archivechart.js index ebcc5ab..f9ec99e 100644 --- a/v2realbot/static/js/archivechart.js +++ b/v2realbot/static/js/archivechart.js @@ -8,6 +8,7 @@ console.log("CHART_SHOW_TEXT archchart", CHART_SHOW_TEXT) // var volumeSeries = null var markersLine = null var avgBuyLine = null +var profitLine = null var slLine = [] //TRANSFORM object returned from REST API get_arch_run_detail //to series and markers required by lightweigth chart @@ -111,6 +112,7 @@ function transform_data(data) { //get markers - avgp line for all buys var avgp_buy_line = [] var avgp_markers = [] + var sum_profit_line = [] var markers = [] var markers_line = [] var last_timestamp = 0.1 @@ -139,9 +141,9 @@ function transform_data(data) { last_timestamp = timestamp iterator = 0.002 } - //puvodne bylo pro buy - //pro sell muzeme teoreticky taky mit buyline (pri shortu) - if ((trade.order.side == "buy") || (trade.order.side == "sell")) { + + //AVG BUY LINE - zatim docasne vypiname + if (((trade.order.side == "buy") || (trade.order.side == "sell")) && 1==2) { //avgp lajnu vytvarime jen pokud je v tradeventu prumerna cena if ((trade.pos_avg_price !== null) && (trade.pos_avg_price !== 0)) { //line pro avgp markers @@ -161,6 +163,26 @@ function transform_data(data) { } } + if ((trade.order.side == "buy") || (trade.order.side == "sell")) { + //avgp lajnu vytvarime jen pokud je v tradeventu prumerna cena + if ((trade.profit_sum !== null)) { + //line pro avgp markers + obj["time"] = timestamp; + obj["value"] = trade.profit_sum.toFixed(1); + sum_profit_line.push(obj) + + //avgp markers pro prumernou cenu aktualnich pozic + // a_markers["time"] = timestamp + // a_markers["position"] = "aboveBar" + // a_markers["color"] = "#e8c76d" + // a_markers["shape"] = "arrowDown" + // a_markers["text"] = trade.profit_sum.toFixed(1); + // //if (CHART_SHOW_TEXT) + // //a_markers["text"] = trade.position_qty + " " + parseFloat(trade.pos_avg_price).toFixed(3) + // //a_markers["text"] = CHART_SHOW_TEXT ? trade.position_qty + "/" + parseFloat(trade.pos_avg_price).toFixed(3) :trade.position_qty + // avgp_markers.push(a_markers) + } + } //buy sell markery @@ -172,7 +194,7 @@ function transform_data(data) { //marker["shape"] = (trade.order.side == "buy") ? "arrowUp" : "arrowDown" marker["shape"] = (trade.order.side == "buy") ? "arrowUp" : "arrowDown" //marker["text"] = trade.qty + "/" + trade.price - qt_optimized = (trade.qty % 1000 === 0) ? (trade.qty / 1000).toFixed(1) + 'K' : trade.qty + qt_optimized = (trade.order.qty % 1000 === 0) ? (trade.order.qty / 1000).toFixed(1) + 'K' : trade.order.qty if (CHART_SHOW_TEXT) { //včetně qty @@ -215,8 +237,10 @@ function transform_data(data) { markers_line.sort(sorter) avgp_buy_line.sort(sorter) avgp_markers.sort(sorter) + sum_profit_line.sort(sorter) - transformed["avgp_buy_line"] = avgp_buy_line + transformed["avgp_buy_line"] = avgp_buy_line + transformed["sum_profit_line"] = sum_profit_line transformed["avgp_markers"] = avgp_markers transformed["markers"] = markers transformed["markers_line"] = markers_line @@ -366,7 +390,15 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { } container1.append(indbuttonElement); + display_buy_markers(); + //TADY JSEM SKONCIL - toto nize predelat na hide button pro display bar markers + // btnElement = document.getElementById("pricelineButtons") + // var indbuttonElement = populate_indicator_buttons(false); + // if (btnElement) { + // container1.removeChild(btnElement); + // } + //container1.append(indbuttonElement); if (last_range) { chart.timeScale().setVisibleRange(last_range); @@ -604,6 +636,11 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { //displays (redraws) buy markers function display_buy_markers() { + + if (profitLine) { + chart.removeSeries(profitLine) + } + if (avgBuyLine) { chart.removeSeries(avgBuyLine) } @@ -650,10 +687,31 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { slLine.push(slLine_temp) //xx - }) + }) //} + if (transformed_data["sum_profit_line"].length > 0) { + profitLine = chart.addLineSeries({ + // title: "avgpbuyline", + color: '#e8c76d', + // color: 'transparent', + lineWidth: 1, + lastValueVisible: false + }); + + profitLine.applyOptions({ + lastValueVisible: false, + priceLineVisible: false, + priceScaleId: "own" + }); + + + profitLine.setData(transformed_data["sum_profit_line"]); + //profitLine.setMarkers(transformed_data["sum_profit_line_markers"]); + } + + if (transformed_data["avgp_buy_line"].length > 0) { avgBuyLine = chart.addLineSeries({ // title: "avgpbuyline", @@ -714,6 +772,7 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { toolTip.innerHTML = ""; var data = param.seriesData.get(markersLine); var data2 = param.seriesData.get(avgBuyLine); + var profitdata = param.seriesData.get(profitLine); if ((data !== undefined) || (data2 !== undefined)) { //param.seriesData.forEach((value, key) => { //console.log("key",key) @@ -733,9 +792,11 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { buy_price = parseFloat(data2.value).toFixed(3) } - toolTip.innerHTML += `