From a3b182fd45271f4c90281a2c4cb489d77cb90763 Mon Sep 17 00:00:00 2001 From: David Brazda Date: Sat, 10 Feb 2024 21:02:00 +0700 Subject: [PATCH] keys to env variables, optimalizations --- v2realbot/config.py | 14 +++++----- v2realbot/loader/aggregator.py | 16 +++++++---- v2realbot/strategy/StrategyClassicSL.py | 12 ++++++--- v2realbot/strategyblocks/newtrade/sizing.py | 14 ++++++++-- v2realbot/tools/sizingpattervisual.py | 30 ++++++++++++++++----- 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/v2realbot/config.py b/v2realbot/config.py index 39988a8..089ee8e 100644 --- a/v2realbot/config.py +++ b/v2realbot/config.py @@ -2,6 +2,7 @@ from alpaca.data.enums import DataFeed from v2realbot.enums.enums import Mode, Account, FillCondition from appdirs import user_data_dir from pathlib import Path +import os #directory for generated images and basic reports MEDIA_DIRECTORY = Path(__file__).parent.parent.parent / "media" @@ -123,23 +124,22 @@ HEARTBEAT_TIMEOUT=5 WEB_API_KEY="david" #PRIMARY PAPER -ACCOUNT1_PAPER_API_KEY = 'PKGGEWIEYZOVQFDRY70L' -ACCOUNT1_PAPER_SECRET_KEY = 'O5Kt8X4RLceIOvM98i5LdbalItsX7hVZlbPYHy8Y' +ACCOUNT1_PAPER_API_KEY = os.environ.get('ACCOUNT1_PAPER_API_KEY') +ACCOUNT1_PAPER_SECRET_KEY = os.environ.get('ACCOUNT1_PAPER_SECRET_KEY') ACCOUNT1_PAPER_MAX_BATCH_SIZE = 1 ACCOUNT1_PAPER_PAPER = True ACCOUNT1_PAPER_FEED = DataFeed.SIP #PRIMARY LIVE -ACCOUNT1_LIVE_API_KEY = 'AKB5HD32LPDZC9TPUWJT' -ACCOUNT1_LIVE_SECRET_KEY = 'Xq1wPSNOtwmlMTAd4cEmdKvNDgfcUYfrOaCccaAs' +ACCOUNT1_LIVE_API_KEY = os.environ.get('ACCOUNT1_LIVE_API_KEY') +ACCOUNT1_LIVE_SECRET_KEY = os.environ.get('ACCOUNT1_LIVE_SECRET_KEY') ACCOUNT1_LIVE_MAX_BATCH_SIZE = 1 ACCOUNT1_LIVE_PAPER = False ACCOUNT1_LIVE_FEED = DataFeed.SIP - #SECONDARY PAPER - Martin -ACCOUNT2_PAPER_API_KEY = 'PKPDTCQLNHCBC2D9GQFB' -ACCOUNT2_PAPER_SECRET_KEY = 'c1Z2V0gBleQmwHYCreqqTs45Jy33RqPGrofuSayz' +ACCOUNT2_PAPER_API_KEY = os.environ.get('ACCOUNT2_PAPER_API_KEY') +ACCOUNT2_PAPER_SECRET_KEY = os.environ.get('ACCOUNT2_PAPER_SECRET_KEY') ACCOUNT2_PAPER_MAX_BATCH_SIZE = 1 ACCOUNT2_PAPER_PAPER = True ACCOUNT2_PAPER_FEED = DataFeed.IEX diff --git a/v2realbot/loader/aggregator.py b/v2realbot/loader/aggregator.py index 6859c87..1b71f22 100644 --- a/v2realbot/loader/aggregator.py +++ b/v2realbot/loader/aggregator.py @@ -48,7 +48,7 @@ class TradeAggregator: self.excludes = excludes self.skip_cache = skip_cache - if mintick >= resolution: + if resolution > 0 and mintick >= resolution: print("Mintick musi byt mensi nez resolution") raise Exception @@ -320,13 +320,13 @@ class TradeAggregator: #TODO: do budoucna vymyslet, kdyz bude mene tradu, tak to radit vzdy do spravneho intervalu #zarovname time prvniho baru podle timeframu kam patří (např. 5, 10, 15 ...) (ROUND) if self.align == StartBarAlign.ROUND and self.bar_start == 0: - t = datetime.fromtimestamp(data['t']) + t = datetime.fromtimestamp(data['t'], tz=zoneUTC) t = t - timedelta(seconds=t.second % self.resolution,microseconds=t.microsecond) self.bar_start = datetime.timestamp(t) #nebo pouzijeme datum tradu zaokrouhlene na vteriny (RANDOM) else: #ulozime si jeho timestamp (odtum pocitame resolution) - t = datetime.fromtimestamp(int(data['t'])) + t = datetime.fromtimestamp(int(data['t']), tz=zoneUTC) #timestamp self.bar_start = int(data['t']) @@ -376,7 +376,7 @@ class TradeAggregator: if self.mintick != 0 and self.lastBarConfirmed: #d zacatku noveho baru musi ubehnout x sekund nez posilame updazte #pocatek noveho baru + Xs musi byt vetsi nez aktualni trade - if (self.newBar['time'] + timedelta(seconds=self.mintick)) > datetime.fromtimestamp(data['t']): + if (self.newBar['time'] + timedelta(seconds=self.mintick)) > datetime.fromtimestamp(data['t'], tz=zoneUTC): #print("waiting for mintick") return [] else: @@ -756,8 +756,14 @@ class TradeAggregator: Ve strategii je třeba počítat s tím, že open v nepotvrzeném baru není finální. """"" + if self.resolution < 0: # Treat as percentage + reference_price = self.lastConfirmedBar['close'] if self.lastConfirmedBar is not None else float(data['p']) + brick_size = abs(self.resolution) * reference_price / 100.0 + else: # Treat as absolute value pocet ticku + brick_size = self.resolution + #pocet ticku např. 10ticků, případně pak na procenta - brick_size = self.resolution + #brick_size = self.resolution #potvrzene pripravene k vraceni confirmedBars = [] #potvrdi existujici a nastavi k vraceni diff --git a/v2realbot/strategy/StrategyClassicSL.py b/v2realbot/strategy/StrategyClassicSL.py index 3d54365..b901453 100644 --- a/v2realbot/strategy/StrategyClassicSL.py +++ b/v2realbot/strategy/StrategyClassicSL.py @@ -41,14 +41,16 @@ class StrategyClassicSL(Strategy): if rel_profit >= float(max_sum_profit_to_quit_rel): self.state.ilog(e=f"QUITTING MAX SUM REL PROFIT REACHED {max_sum_profit_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.state.vars.pending = "max_sum_profit_to_quit_rel" - send_to_telegram(f"QUITTING MAX SUM REL PROFIT REACHED {max_sum_profit_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") + if self.mode not in [Mode.BT, Mode.PREP]: + send_to_telegram(f"QUITTING MAX SUM REL PROFIT REACHED {max_sum_profit_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.signal_stop = True return True if max_sum_loss_to_quit_rel is not None: if rel_profit < 0 and rel_profit <= float(max_sum_loss_to_quit_rel): self.state.ilog(e=f"QUITTING MAX SUM REL LOSS REACHED {max_sum_loss_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.state.vars.pending = "max_sum_loss_to_quit_rel" - send_to_telegram(f"QUITTING MAX SUM REL LOSS REACHED {max_sum_loss_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") + if self.mode not in [Mode.BT, Mode.PREP]: + send_to_telegram(f"QUITTING MAX SUM REL LOSS REACHED {max_sum_loss_to_quit_rel=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.signal_stop = True return True @@ -56,14 +58,16 @@ class StrategyClassicSL(Strategy): if float(self.state.profit) >= float(max_sum_profit_to_quit): self.state.ilog(e=f"QUITTING MAX SUM ABS PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.state.vars.pending = "max_sum_profit_to_quit" - send_to_telegram(f"QUITTING MAX SUM ABS PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") + if self.mode not in [Mode.BT, Mode.PREP]: + send_to_telegram(f"QUITTING MAX SUM ABS PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.signal_stop = True return True if max_sum_loss_to_quit is not None: if float(self.state.profit) < 0 and float(self.state.profit) <= float(max_sum_loss_to_quit): self.state.ilog(e=f"QUITTING MAX SUM ABS LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.state.vars.pending = "max_sum_loss_to_quit" - send_to_telegram(f"QUITTING MAX SUM ABS LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") + if self.mode not in [Mode.BT, Mode.PREP]: + send_to_telegram(f"QUITTING MAX SUM ABS LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=} {rel_profit=} relprofits:{str(self.state.rel_profit_cum)}") self.signal_stop = True return True diff --git a/v2realbot/strategyblocks/newtrade/sizing.py b/v2realbot/strategyblocks/newtrade/sizing.py index a6a76e6..f670842 100644 --- a/v2realbot/strategyblocks/newtrade/sizing.py +++ b/v2realbot/strategyblocks/newtrade/sizing.py @@ -9,6 +9,7 @@ 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 +from scipy.interpolate import interp1d def get_size(state: StrategyState, data, signaloptions: dict, direction: TradeDirection): return state.vars.chunk * get_multiplier(state, signaloptions, direction) @@ -133,8 +134,17 @@ def get_multiplier(state: StrategyState, data, signaloptions: dict, direction: T 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 - Input value of {pattern_source} value {input_value}", options=options, time=state.time) + + #puvodni jednoducha interpolace + #multiplier = np.interp(input_value, pattern_source_axis, pattern_size_axis) + + # Updated interpolation function for smoother results + # Create the interpolation function + f = interp1d(pattern_source_axis, pattern_size_axis, kind='cubic') + + # Interpolate the input value using the interpolation function + multiplier = f(input_value) 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: diff --git a/v2realbot/tools/sizingpattervisual.py b/v2realbot/tools/sizingpattervisual.py index b5716a5..e72178d 100644 --- a/v2realbot/tools/sizingpattervisual.py +++ b/v2realbot/tools/sizingpattervisual.py @@ -1,6 +1,6 @@ import numpy as np +from scipy.interpolate import interp1d import matplotlib.pyplot as plt - # Sem zadat pattern X a Y pro VIZUALIZACI #minutes @@ -14,16 +14,34 @@ pattern_y = [0.1, 0.5, 0.8, 1, 0.6, 0.1] #celkový profit # Generating a range of input values for interpolation -input_values = np.linspace(min(pattern_x), max(pattern_x), 500) -multipliers = np.interp(input_values, pattern_x, pattern_y) +input_values = np.linspace(min(pattern_x), max(pattern_x), 1000) # Increase the number of points -# Plotting +# Bezier interpolation +interp_func = interp1d(pattern_x, pattern_y, kind='cubic') +multipliers_cubic = interp_func(input_values) + +multipliers_linear = np.interp(input_values, pattern_x, pattern_y) + + +# Plotting multipliers_linear and multipliers_cubic on the same canvas plt.figure(figsize=(10, 6)) plt.plot(pattern_x, pattern_y, 'o', label='Original Points') -plt.plot(input_values, multipliers, label='Interpolated Values') +plt.plot(input_values, multipliers_linear, label='Linear Interpolation') +plt.plot(input_values, multipliers_cubic, label='Cubic Interpolation') plt.xlabel('X values') plt.ylabel('Interpolated Multipliers') -plt.title('Interpolation Chart') +plt.title('Interpolation Comparison') plt.legend() plt.grid(True) plt.show() + +# # Plotting multipliers_cubic +# plt.figure(figsize=(10, 6)) +# plt.plot(pattern_x, pattern_y, 'o', label='Original Points') +# plt.plot(input_values, multipliers_cubic, label='Cubic Interpolation') +# plt.xlabel('X values') +# plt.ylabel('Interpolated Multipliers') +# plt.title('Cubic Interpolation Chart') +# plt.legend() +# plt.grid(True) +# plt.show()