agregace volume baru, SL optimizace + goalprice

This commit is contained in:
David Brazda
2023-11-07 17:57:08 +01:00
parent 0db88b194c
commit b7f148fadd
24 changed files with 797 additions and 101 deletions

6
testy/ascending.py Normal file

File diff suppressed because one or more lines are too long

179
testy/fibonaccistoploss.py Normal file
View File

@ -0,0 +1,179 @@
import numpy as np
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus
from typing import Tuple
from copy import deepcopy
from v2realbot.strategy.base import StrategyState
from v2realbot.strategyblocks.activetrade.helpers import get_max_profit_price, get_profit_target_price, get_override_for_active_trade, keyword_conditions_met
from v2realbot.utils.utils import safe_get
# FIBONACCI PRO PROFIT A SL
##most used fibonacci retracement levels
# 23.6% retracement level = (stop loss price - current price) * 0.236 + current price
# 38.2% retracement level = (stop loss price - current price) * 0.382 + current price
# 50.0% retracement level = (stop loss price - current price) * 0.500 + current price
# 61.8% retracement level = (stop loss price - current price) * 0.618 + current price
# 78.6% retracement level = (stop loss price - current price) * 0.786 + current price
#cil: moznost pouzit fibanocci scale pro castecny stoploss exit (percentage at each downlevel)
#a zároveň exit, případně add at each up level
#up retracements (profit retracement)
# exit part of position at certain -
# [0.236, 0.382, 0.618, 1.0] - 25% off at each level? a nebo 5% add? - TBD vymyslet jak pojmout v direktive?
#down retracement (stoploss retracement)
# exit part of position at certain levels - TBD jak zapsat v dsirektive?
# [0.236, 0.382, 0.618, 1.0] - 25% off at each level
# #tridu, kterou muze vyuzivat SL a Profit optimizer
class SLOptimizer:
""""
Class to handle SL positition optimization for active trade. It is assumed that two instances exists
one for LONG trade and one for SHORT. During evaluate call, settings is initialized from trade setting
and used for every call on that trade. When evaluate is called on different trade, it is again initialized
according to new trade settings.
-samostatna instance pro short a long
-zatim pri opakovem prekroceni targetu nic nedelame (target aplikovany jen jednouo)
exit_levels = aktuální levely, prekroceny je povazovan za vyuzitý a maze se
exit_sizes = aktualní size multipliers, prekroceny je povazovan za vyuzitý a maze se
init_exit_levels, init_exit_sizes - puvodni plne
"""
def __init__(self, direction: TradeDirection) -> None:
##init - make exit size same length:
self.direction = direction
self.last_trade = 0
# def reset_levels(self):
# self.exit_levels = self.init_exit_levels
# self.exit_sizes = self.init_exit_sizes
def get_trade_details(self, state: StrategyState):
trade: Trade = state.vars.activeTrade
#jde o novy trade - resetujeme levely
if trade.id != self.last_trade:
#inicializujeme a vymazeme pripadne puvodni
if self.initialize_levels(state) is False:
return None, None
self.last_trade = trade.id
#return cost_price, sl_price
return state.avgp, trade.stoploss_value
def initialize_levels(self, state):
directive_name = 'SL_opt_exit_levels_'+str(self.direction)
SL_opt_exit_levels = get_override_for_active_trade(state=state, directive_name=directive_name, default_value=safe_get(state.vars, directive_name, None))
directive_name = 'SL_opt_exit_sizes_'+str(self.direction)
SL_opt_exit_sizes = get_override_for_active_trade(state=state, directive_name=directive_name, default_value=safe_get(state.vars, directive_name, None))
if SL_opt_exit_levels is None or SL_opt_exit_sizes is not None:
print("no directives found: SL_opt_exit_levels/SL_opt_exit_sizes")
return False
if len(SL_opt_exit_sizes) == 1:
SL_opt_exit_sizes = SL_opt_exit_sizes * len(SL_opt_exit_levels)
if len(SL_opt_exit_sizes) != len(SL_opt_exit_levels):
raise Exception("exit_sizes doesnt fit exit_levels")
self.init_exit_levels = deepcopy(SL_opt_exit_levels)
self.init_exit_sizes = deepcopy(SL_opt_exit_sizes)
self.exit_levels = SL_opt_exit_levels
self.exit_sizes = SL_opt_exit_sizes
print(f"new levels initialized {self.exit_levels=} {self.exit_sizes=}")
return True
def get_initial_abs_levels(self, state):
"""
Returns price levels corresponding to initial setting of exit_levels
"""
cost_price, sl_price = self.get_trade_details(state)
if cost_price is None or sl_price is None:
return []
curr_sl_distance = np.abs(cost_price - sl_price)
if self.direction == TradeDirection.SHORT :
return [cost_price + exit_level * curr_sl_distance for exit_level in self.init_exit_levels]
else:
return [cost_price - exit_level * curr_sl_distance for exit_level in self.init_exit_levels]
def get_remaining_abs_levels(self, state):
"""
Returns price levels corresponding to remaing exit_levels for current trade
"""
cost_price, sl_price = self.get_trade_details(state)
if cost_price is None or sl_price is None:
return []
curr_sl_distance = np.abs(cost_price - sl_price)
if self.direction == TradeDirection.SHORT :
return [cost_price + exit_level * curr_sl_distance for exit_level in self.exit_levels]
else:
return [cost_price - exit_level * curr_sl_distance for exit_level in self.exit_levels]
def eval_position(self, state, data) -> Tuple[float, float]:
"""Evaluates optimalization for current position and returns if the given level was
met and how to adjust exit position.
"""
cost_price, sl_price = self.get_trade_details(state)
if cost_price is None or sl_price is None:
print("no settings found")
return (None, None)
current_price = data["close"]
# Calculate the distance of the cost prcie from the stop-loss value
curr_sl_distance = np.abs(cost_price - sl_price)
level_met = None
exit_adjustment = None
if len(self.exit_levels) == 0 or len(self.exit_sizes) == 0:
print("levels exhausted")
return (None, None)
#for short
if self.direction == TradeDirection.SHORT :
#first available exit point
level_price = cost_price + self.exit_levels[0] * curr_sl_distance
if current_price > level_price:
# Remove the first element from exit_levels.
level_met = self.exit_levels.pop(0)
# Remove the first element from exit_sizes.
exit_adjustment = self.exit_sizes.pop(0)
#for shorts
else:
#price of first available exit point
level_price = cost_price - self.exit_levels[0] * curr_sl_distance
if current_price < level_price:
# Remove the first element from exit_levels.
level_met = self.exit_levels.pop(0)
# Remove the first element from exit_sizes.
exit_adjustment = self.exit_sizes.pop(0)
return level_met, exit_adjustment
#0.236, 0.382, 0.5, 0.618, 0.786, 1
exit_levels_input = [0.236, 0.382, 0.618, 1]
exit_sizes_input = [0.5] #or [0.25, 0.25, 0.25]
long_sl_optimizer = SLOptimizer(exit_levels_input, exit_sizes_input, TradeDirection.SHORT)
#short_sl_optimizer = SLOptimizer(exit_levels, exit_sizes, TradeDirection.SHORT)
print(long_sl_optimizer.get_remaining_abs_levels(90,100))
#new LONG trade
level_met, exit_adjustment = long_sl_optimizer.eval_position(current_price=95,cost_price=90,sl_price=100)
print(long_sl_optimizer.get_remaining_abs_levels(90,100))
print(level_met, exit_adjustment)
print(long_sl_optimizer.__dict__)
level_met, exit_adjustment = long_sl_optimizer.eval_position(current_price=95,cost_price=90,sl_price=100)
print(long_sl_optimizer.get_remaining_abs_levels(90,100))
print(level_met, exit_adjustment)
print(long_sl_optimizer.__dict__)
level_met, exit_adjustment = long_sl_optimizer.eval_position(current_price=95,cost_price=90,sl_price=100)
print(long_sl_optimizer.get_remaining_abs_levels(90,100))
print(level_met, exit_adjustment)
print(long_sl_optimizer.__dict__)
#long_sl_optimizer.eval_position(100,120)