sizing, progressionbar,reporting basics

This commit is contained in:
David Brazda
2023-11-20 17:55:55 +01:00
parent 520b1a9a8f
commit 67d34481c6
19 changed files with 1032 additions and 54 deletions

View File

@ -82,7 +82,10 @@ def get_source_series(state, source: str):
try:
return state.bars[source]
except KeyError:
return state.indicators[source]
try:
return state.indicators[source]
except KeyError:
return None
else:
dict_name = source[:split_index]
key = source[split_index + 1:]

View File

@ -7,6 +7,7 @@ from datetime import datetime
from rich import print as printanyway
from traceback import format_exc
from v2realbot.strategyblocks.newtrade.conditions import go_conditions_met, common_go_preconditions_check
from v2realbot.strategyblocks.newtrade.sizing import get_size, get_multiplier
def signal_search(state: StrategyState, data):
# SIGNAL sekce ve stratvars obsahuje signaly: Ty se skladaji z obecnych parametru a podsekce podminek.
@ -42,7 +43,7 @@ def execute_signal_generator(state, data, name):
options = safe_get(state.vars.signals, name, None)
if options is None:
state.ilog(lvl=1,e="No options for {name} in stratvars")
state.ilog(lvl=1,e=f"No options for {name} in stratvars")
return
if common_go_preconditions_check(state, data, signalname=name, options=options) is False:
@ -71,20 +72,26 @@ def execute_signal_generator(state, data, name):
if long_enabled is False:
state.ilog(lvl=1,e=f"{name} LONG DISABLED")
if long_enabled and go_conditions_met(state, data,signalname=name, direction=TradeDirection.LONG):
multiplier = get_multiplier(state, data, options, TradeDirection.LONG)
state.vars.prescribedTrades.append(Trade(
id=uuid4(),
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
status=TradeStatus.READY,
generated_by=name,
size=multiplier*state.vars.chunk,
size_multiplier = multiplier,
direction=TradeDirection.LONG,
entry_price=None,
stoploss_value = None))
elif short_enabled and go_conditions_met(state, data, signalname=name, direction=TradeDirection.SHORT):
multiplier = get_multiplier(state, data, options, TradeDirection.SHORT)
state.vars.prescribedTrades.append(Trade(
id=uuid4(),
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
status=TradeStatus.READY,
generated_by=name,
size=multiplier*state.vars.chunk,
size_multiplier = multiplier,
direction=TradeDirection.SHORT,
entry_price=None,
stoploss_value = None))

View File

@ -0,0 +1,143 @@
from v2realbot.strategy.base import StrategyState
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus
import v2realbot.utils.utils as utls
from v2realbot.config import KW
from uuid import uuid4
from datetime import datetime
from rich import print as printanyway
from traceback import format_exc
from v2realbot.strategyblocks.newtrade.conditions import go_conditions_met, common_go_preconditions_check
from v2realbot.strategyblocks.indicators.helpers import get_source_series
import numpy as np
def get_size(state: StrategyState, data, signaloptions: dict, direction: TradeDirection):
return state.vars.chunk * get_multiplier(state, signaloptions, direction)
def get_multiplier(state: StrategyState, data, signaloptions: dict, direction: TradeDirection):
""""
Function return dynamic sizing multiplier according to directive and current trades.
Default: state.vars.chunk
Additional sizing logic is layered on top of each other according to directives.
Currently supporting:
1) pattern sizing U-shape, hat-shape (x - bars, minutes, y - sizing multiplier 0 to 1 )
2) probes
Future ideas:
- ML sizing model
DIRECTIVES:
#sondy na zacatku market
probe_enabled = true # sonda zapnuta
number = 1 # pocet sond
probe_size = 0.01 #velikost sondy, nasobek def size
#pattern - dynamicka uprava na zaklade casu
pattern_enabled = true
pattern_source = "minutes" #or any series - indicators, bars or state etc. (index[-1], np.sum(state.rel_profit_cum)...)
pattern_source_vals = [0,30,90, 200, 300, 390]
pattern_sizing_vals = [0.1,0.5, 0.8, 1, 0.6, 0.1]
#np.interp(atr10, [0.001, 0.06], [1, 5])
#size_multiplier = np.interp(pattern_source, [SIZING_pattern_source_vals], [SIZING_pattern_sizing_vals])
#TODO
- pomocna graf pro vizualizaci interpolace - v tools/sizingpatternvisual.py
- dopsat do dokumentace direktiv - do tabulky
- ukládat sizing coeff do prescrTrades
- upravit výpočet denního relativniho profitu u tradu na základě vstupního sizing koeficientu
- vyresit zda max_oss_to_quit_rel aplikovat bud per alokovana pozice nebo trade
(pokud mam na trade, pak mi zafunguje i na minimalni sodnu) Zatim bude
realizován takto
- nejprve ověří rel profit tradu a pokud přesáhne, strategie se suspendne
- poté se rel profit tradu vynásobí multiplikátorem a započte se do denního rel profitu, jehož
výše se následně také ověří
NOTE: zatim neupraveno, a do denniho rel profitu se zapocitava plnym pomerem, diky tomu
si muzu dat i na sondu -0.5 suspend strategie. Nevyhoda: rel.profit presne neodpovida
[stratvars.signals.morning1.sizing] #specificke pro dany signal
probe_enabled = true
probe_size = 0.01
pattern_enabled = true
# pattern_source = "minutes" #or any series - indicators, bars or state etc. (index[-1], np.sum(state.rel_profit_cum)...)
pattern_source_axis = [0,30,90, 200, 300, 390]
pattern_size_axis = [0.1,0.5, 0.8, 1, 0.6, 0.1]
[stratvars.sizing] #obecne jako fallback pro vsechny signaly
probe_enabled = true
probe_size = 0.01
pattern_enabled = true
# pattern_source = "minutes" #or any series - indicators, bars or state etc. (index[-1], np.sum(state.rel_profit_cum)...)
pattern_source_axis = [0,30,90, 200, 300, 390]
pattern_size_axis = [0.1,0.5, 0.8, 1, 0.6, 0.1]
"""""
multiplier = 1
#fallback common sizing sekci
fallback_options = utls.safe_get(state.vars, 'sizing', None)
#signal specific sekce
options = utls.safe_get(signaloptions, 'sizing', fallback_options)
if options is None:
state.ilog(lvl=1,e="No sizing options common or signal specific in stratvars")
return multiplier
#PROBE ENABLED
# probe_enabled = true # sonda zapnuta
# probe_number = 1 # pocet sond
# probe_size = 0.01 #velikost sondy, nasobek def size
probe_enabled = utls.safe_get(options, "probe_enabled", False)
if probe_enabled:
#zatim pouze probe number 1 natvrdo, tzn. nesmi byt trade pro aktivace
if state.vars.last_in_index is None:
#probe_number = utls.safe_get(options, "probe_number",1)
probe_size = float(utls.safe_get(options, "probe_size", 0.1))
state.ilog(lvl=1,e=f"SIZER - PROBE - setting multiplier to {probe_size}", options=options)
return probe_size
#SIZING PATTER
# pattern_enabled = true
# pattern_source = "minutes" #or any series - indicators, bars or state etc. (index[-1], np.sum(state.rel_profit_cum)...)
# pattern_source_axis = [0,30,90, 200, 300, 390]
# pattern_size_axis = [0.1,0.5, 0.8, 1, 0.6, 0.1]
pattern_enabled = utls.safe_get(options, "pattern_enabled", False)
if pattern_enabled:
input_value = None
pattern_source = utls.safe_get(options, "pattern_source", "minutes")
#TODO do budoucna mozna sem dát libovolnou series např. index, time, profit, rel_profit?
if pattern_source != "minutes":
input_value = eval(pattern_source, {'state': state, 'np': np, 'utls': utls}, state.ind_mapping)
if input_value is None:
state.ilog(lvl=1,e=f"SIZER - ERROR Pattern source is None, after evaluation of expression", options=str(options))
return multiplier
else:
input_value = utls.minutes_since_market_open(datetime.fromtimestamp(data['updated']).astimezone(utls.zoneNY))
pattern_source_axis = utls.safe_get(options, "pattern_source_axis", None)
pattern_size_axis = utls.safe_get(options, "pattern_size_axis", None)
if pattern_source_axis is None or pattern_size_axis is None:
state.ilog(lvl=1,e=f"SIZER - Pattern source and size axis must be set", options=str(options))
return multiplier
state.ilog(lvl=1,e=f"SIZER - Input value of {pattern_source} value {input_value}", options=options, time=state.time)
multiplier = np.interp(input_value, pattern_source_axis, pattern_size_axis)
state.ilog(lvl=1,e=f"SIZER - Interpolated value {multiplier}", input_value=input_value, pattern_source_axis=pattern_source_axis, pattern_size_axis=pattern_size_axis, options=options, time=state.time)
if multiplier > 1 or multiplier <= 0:
state.ilog(lvl=1,e=f"SIZER - Mame nekde problem MULTIPLIER mimo RANGE ERROR {multiplier}", options=options, time=state.time)
multiplier = 1
return multiplier