From f36335d61fe04f1700cf5a149db1cabcd4fd488f Mon Sep 17 00:00:00 2001 From: adonunes Date: Tue, 30 Apr 2024 07:27:38 -0400 Subject: [PATCH] fix ndx webull --- DiscordAlertsTrader/brokerages/weBull_api.py | 4 +-- DiscordAlertsTrader/calc_strat.py | 26 +++++++++---------- .../marketdata/load_chn_hist.py | 11 ++++++-- .../marketdata/thetadata_api.py | 1 + DiscordAlertsTrader/port_sim.py | 12 ++++----- DiscordAlertsTrader/read_hist_msg.py | 20 ++++++++++++++ 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/DiscordAlertsTrader/brokerages/weBull_api.py b/DiscordAlertsTrader/brokerages/weBull_api.py index b67c46e..6016e8b 100644 --- a/DiscordAlertsTrader/brokerages/weBull_api.py +++ b/DiscordAlertsTrader/brokerages/weBull_api.py @@ -180,9 +180,9 @@ def get_option_id(self, symb:str): def fix_symbol(self, symbol:str, direction:str): "Fix symbol for options, direction in or out of webull format" if direction == 'in': - return symbol.replace("SPXW", "SPX") + return symbol.replace("SPXW", "SPX").replace("NDXP", "NDX") elif direction == 'out': - return symbol.replace("SPX", "SPXW") + return symbol.replace("SPX", "SPXW").replace("NDX", "NDXP") def get_quotes(self, symbol:list) -> dict: resp = {} diff --git a/DiscordAlertsTrader/calc_strat.py b/DiscordAlertsTrader/calc_strat.py index ad67b98..93ed3a5 100644 --- a/DiscordAlertsTrader/calc_strat.py +++ b/DiscordAlertsTrader/calc_strat.py @@ -682,9 +682,9 @@ def grid_search(params_dict, PT=[60], TS=[0], SL=[45], TS_buy=[5,10,15,20,25]): dir_quotes = cfg['general']['data_dir'] + '/live_quotes' params = { - 'fname_port': 'data/oculus_port.csv', + 'fname_port': 'data/rough_port.csv', 'order_type': 'any', - 'last_days': 30, + 'last_days': 400, 'filt_date_frm': "", 'filt_date_to': "", 'stc_date':'eod',#'exp', #,'stc alert', #'exp',# , # # 'eod' or @@ -693,26 +693,26 @@ def grid_search(params_dict, PT=[60], TS=[0], SL=[45], TS_buy=[5,10,15,20,25]): 'max_dte': 10, 'min_dte': 0, 'filt_hour_frm': "", - 'filt_hour_to': "", + 'filt_hour_to': 12, 'include_authors': "", 'exclude_symbols': [], - 'initial_price' : 'ask', # 'ask_+10', - 'PT': [90], #[20,25,35,45,55,65,95,],# [90],# + 'initial_price' : 'ask_+30', # 'ask_+10', + 'PT': [50], #[20,25,35,45,55,65,95,],# [90],# 'pts_ratio' :[1],#[0.2,0.2,0.2,0.1,0.1,0.1,0.1,],# [0.4, 0.3, 0.3], # 'sl_update' : None, # [[1.20, 1.05], [1.5, 1.3]], # - "pt_update" : [ [.3,0.7]], # None, # - 'avg_down':[[1.5, 1]], # [[1.1, .1],[1.2, .1],[1.3, .1],[1.4, .2],[1.5, .2],[1.6, .2]], # - 'SL': 90, + # "pt_update" : [ [.3,0.7]], # None, # + # 'avg_down':[[1.5, 1]], # [[1.1, .1],[1.2, .1],[1.3, .1],[1.4, .2],[1.5, .2],[1.6, .2]], # + 'SL': 40, 'TS': 0, 'TS_buy': 0, 'TS_buy_type':'inverse', # 'max_margin': 100000, 'short_under_amnt' : 2000, - 'min_trade_val': .01, + 'min_trade_val': 10, 'verbose': True, 'trade_amount': 1000, - # "sell_bto": True, - # "max_short_val": 4000, + "sell_bto": True, + "max_short_val": 4000, "invert_contracts": False, "do_plot": False } @@ -728,7 +728,7 @@ def grid_search(params_dict, PT=[60], TS=[0], SL=[45], TS_buy=[5,10,15,20,25]): result_td = generate_report(port, param, None, verbose=True) - if 0: + if 1: import matplotlib.pyplot as plt stat_type = 'strategy-PnL' # 'PnL' # 'PnL-actual'# @@ -769,7 +769,7 @@ def grid_search(params_dict, PT=[60], TS=[0], SL=[45], TS_buy=[5,10,15,20,25]): port[stat_type].plot(ax=axs[1,1], title=stat_type, grid=True, marker='o', linestyle='dotted') axs[1,1].set_xlabel("Trade number") axs[1,1].set_ylabel("%") - plt.show(block=True) + plt.show(block=False) if 0: params['theta_client'] = client diff --git a/DiscordAlertsTrader/marketdata/load_chn_hist.py b/DiscordAlertsTrader/marketdata/load_chn_hist.py index 7eb4233..ede5cc6 100644 --- a/DiscordAlertsTrader/marketdata/load_chn_hist.py +++ b/DiscordAlertsTrader/marketdata/load_chn_hist.py @@ -22,7 +22,7 @@ get_date_after_from_port = True re_download = False delete_port = False -author = "vader" +author = "rough" def get_timestamp(row): @@ -84,6 +84,7 @@ def save_or_append_quote(quotes, symbol, path_quotes, overwrite=False): "og-alerts": 1207717868716826645, "EM": 1126325195301462117, "vader-swings":1223379548675117088, + "rough": 989674163331534929, } chan_id = chan_ids[author] if not use_theta_rest_api: @@ -169,7 +170,7 @@ def save_or_append_quote(quotes, symbol, path_quotes, overwrite=False): ) dt = None -for ix, row in msg_hist.iterrows(): # .loc[ix:].iterrows(): # +for ix, row in msg_hist.loc[ix:].iterrows(): # .loc[ix:].iterrows(): # print(ix) alert = row["Content"] if pd.isnull(alert) or not len(alert) or alert in ["@everyone", "@Elite Options"]: @@ -201,6 +202,12 @@ def save_or_append_quote(quotes, symbol, path_quotes, overwrite=False): if len(full_date.split("/")) == 2 else "%m/%d/%Y" if len(full_date.split("/")[2]) == 4 else "%m/%d/%y" ) + try: + datetime.strptime(full_date, dt_fm).date() + except ValueError: + print("Incorrect date format", full_date, dt_fm) + continue + if datetime.strptime(full_date, dt_fm).date() < dt.date(): print("Order date in the past, skipping", order["expDate"], order["Date"]) resp = tracker.trade_alert(order, live_alert=False, channel=author) diff --git a/DiscordAlertsTrader/marketdata/thetadata_api.py b/DiscordAlertsTrader/marketdata/thetadata_api.py index f0670a6..beb8864 100644 --- a/DiscordAlertsTrader/marketdata/thetadata_api.py +++ b/DiscordAlertsTrader/marketdata/thetadata_api.py @@ -281,6 +281,7 @@ def get_hist_quotes(self, symbol: str, date_range: List[date], interval_size: in # data = data[(data['ask']!=0)] # remove zero ask & (data['bid']!=0) save_or_append_quote(data, symbol, self.dir_quotes) + return data def get_hist_quotes_stock(self, symbol: str, date_range: List[date], interval_size: int=1000): diff --git a/DiscordAlertsTrader/port_sim.py b/DiscordAlertsTrader/port_sim.py index fbd9684..e98dec2 100644 --- a/DiscordAlertsTrader/port_sim.py +++ b/DiscordAlertsTrader/port_sim.py @@ -461,7 +461,7 @@ def calc_roi(quotes:pd.Series, PT:float, TS:float, SL:float, do_plot:bool=False, list of tuples with target and new profit target, eg [(1.1, 1.2)] at 10% change PT to 20%, by default None ask : pd.Series - ask quote, used to calculate SL + ask quote, used to calculate SL (use bid if STO) last : pd.Series last quote, used to calculate SL action : str, optional @@ -487,7 +487,7 @@ def calc_roi(quotes:pd.Series, PT:float, TS:float, SL:float, do_plot:bool=False, ask = ask[msk] if initial_prices is None: - initial_price = quotes.iloc[0] + initial_price = ask.iloc[0] else: initial_price = initial_prices sl = initial_price * SL @@ -552,7 +552,7 @@ def calc_roi(quotes:pd.Series, PT:float, TS:float, SL:float, do_plot:bool=False, new_update.append([initial_price *upt, initial_price * usl]) # print(f"initial {initial_price}, PT {pt} Sl {sl} update{new_update}") if act == "S": - sl_index, sl_val = calc_SL(quotes, sl, new_update) + sl_index, sl_val = calc_SL(ask, sl, new_update) else: sl_index, sl_val = calc_SL(last, sl, new_update) if sl_index is not None: @@ -564,11 +564,11 @@ def calc_roi(quotes:pd.Series, PT:float, TS:float, SL:float, do_plot:bool=False, # no TP no SL, then use the last value if trigger_index is None and sl_index is None: - sell_price = quotes.iloc[-1] + sell_price = last.iloc[-1] no_ts_sell = sell_price - sell_index = quotes.index[-1] + sell_index = last.index[-1] if do_plot: - plt.plot(quotes.index[len(quotes)-1], (quotes.iloc[-1]-quotes.iloc[0])/quotes.iloc[0], marker='o', alpha=.5) + plt.plot(last.index[len(last)-1], (last.iloc[-1]-last.iloc[0])/last.iloc[0], marker='o', alpha=.5) # no TP, use SL elif trigger_index is None: sell_price = sl_val diff --git a/DiscordAlertsTrader/read_hist_msg.py b/DiscordAlertsTrader/read_hist_msg.py index 1b1a5fd..f464947 100644 --- a/DiscordAlertsTrader/read_hist_msg.py +++ b/DiscordAlertsTrader/read_hist_msg.py @@ -41,6 +41,23 @@ def kent_formatting(message): alert += mb['description'] return alert + +def rough_formatting(message): + """ + Reformat Discord message from rough to content message + """ + alert = message['content'] + if message['content'] is None: + return "" + + pattern = r'\b(BTO)?\b(\d{1,2}\/\d{1,2})?\s*([A-Z]+)\s*(\d+[.\d+]*[c|p|C|P])\s*@\s*(\d+(?:[.]\d+)?|\.\d+)' + match = re.search(pattern, alert, re.IGNORECASE) + if match: + action, expDate, ticker, strike, price = match.groups() + alert = f"BTO {ticker} {strike.upper()} {expDate} @{price}" + return alert + + def pbt_formatting(message): """ Reformat Discord message from PBT @@ -468,6 +485,9 @@ def parse_hist_msg(fname, author): elif author == "pbt": content = pbt_formatting(msg) msg["author"]["name"] = "pbt" + elif author == "rough": + content = rough_formatting(msg) + msg["author"]["name"] = "rough" pars, order = parse_trade_alert(content)