Skip to content

Commit ebc2e91

Browse files
susansusan
authored andcommitted
unify filter logic
1 parent 0c1383e commit ebc2e91

File tree

4 files changed

+80
-45
lines changed

4 files changed

+80
-45
lines changed

get_besteu.py

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import logging
55
import pandas as pd
66
import opchain
7+
import time
78

89
def eprint(*args, **kwargs):
910
print(*args, file=sys.stderr, **kwargs)
@@ -12,9 +13,9 @@ def eprint(*args, **kwargs):
1213
MIN_DMU2 = -8.0
1314
MIN_DME_U = -999.0
1415
MIN_MG = 0.5
15-
ODD_DAY_SYMBOLS = ["DJI.C", "DIA", "$SPX.X", "SPY", "$NDX.X", "QQQ", "$RUT.X", "IWM", "$VIX.X", "VXX"]
16+
ODD_DAY_SYMBOLS = ["DJI.C", "DIA", "$SPX.X", "SPY", "$NDX.X", "QQQ", "$RUT.X", "IWM", "$VIX.X", "VXX", "EWZ"] #brazil
1617
MIN_DAY = 38
17-
MAX_DAY = 112
18+
MAX_DAY = 78
1819
MIN_EW = -1.0
1920
MIN_DME_W = 0.0
2021
NUM_EWS = 30
@@ -37,12 +38,12 @@ def eprint(*args, **kwargs):
3738
"dme",
3839
#"DME_u",
3940
"dme_w",
41+
"e_w",
42+
"mg_w",
4043
"pop",
4144
# "popt",
4245
"width",
4346
#"e_u",
44-
"e_w",
45-
"mg_w",
4647
#"eml_u",
4748
#"ml_u",
4849
#"mg_u",
@@ -130,7 +131,7 @@ def getBestEw(df, daysToExpiration=None, count=1):
130131
return rows
131132

132133

133-
def getBestEws(stocklist_file, rows, run_date=None, exp_days=None):
134+
def getBestEUs(stocklist_file, rows, run_date=None, exp_days=None):
134135
if not os.path.isfile(stocklist_file):
135136
eprint(f"{stocklist_file} not found")
136137
sys.exit(1)
@@ -183,6 +184,46 @@ def getBestEws(stocklist_file, rows, run_date=None, exp_days=None):
183184
eprint(f"got data for {len(symbols)} symbols {symbols} from file: {stocklist_file}")
184185

185186

187+
def minmaxFilter(df, use_odd_day_symbols=False):
188+
logging.info(f"df minmaxstart: {len(df)} rows")
189+
df = df[df.days_exp >= MIN_DAY]
190+
df = df[df.days_exp <= MAX_DAY]
191+
logging.info(f"len after min/max days: {len(df)}")
192+
df = df[df.e_w > MIN_EW]
193+
logging.info(f"len after > MIN_EW: {len(df)}")
194+
#df = df.drop(df[df.dmu <= MIN_DMU].index)
195+
df = df[df.dmu >= MIN_DMU]
196+
logging.info(f"len after <= MIN_DMU: {len(df)}")
197+
# df = df.drop(df[df.dmu2 <= MIN_DMU2].index)
198+
df = df[df.dmu2 >= MIN_DMU2]
199+
logging.info(f"len after <= MIN_DMU2: {len(df)}")
200+
# df = df.drop(df[df.dme_u <= MIN_DME_U].index)
201+
logging.debug(f"dme_w max: {df.dme_w.max()}")
202+
logging.debug(f"dme_w min: {df.dme_w.min()}")
203+
#df = df.drop(df[df.dme_w <= MIN_DME_W].index)
204+
df = df[df.dme_w > MIN_DME_W]
205+
logging.info(f"len after > MIN_DME_W: {len(df)}")
206+
# df = df.drop(df[df.mg <= MIN_MG].index)
207+
df = df[df.mg >= MIN_MG]
208+
logging.info(f"len after <= MIN_MG: {len(df)}")
209+
if len(df) == 0:
210+
logging.info("no rows, returning empty dataframe")
211+
return df
212+
213+
#eprint("symbols:", df['symbol'])
214+
eprint("df minmaxstart start filter symbols:", len(df))
215+
if use_odd_day_symbols:
216+
df = df[df.symbol.isin(ODD_DAY_SYMBOLS)]
217+
else:
218+
eprint("filtered symbols")
219+
df = df[~df.symbol.isin(ODD_DAY_SYMBOLS)]
220+
221+
eprint("trimed df:", len(df))
222+
223+
df = df.sort_values(by="dme_w", ascending=False) # DME_u
224+
return df
225+
226+
186227
# main
187228
#
188229
if len(sys.argv) < 2 or sys.argv[1] in ('-h', '--help'):
@@ -218,27 +259,29 @@ def getBestEws(stocklist_file, rows, run_date=None, exp_days=None):
218259

219260
# assume it's a csv file of symbols
220261
rows = []
262+
start_time = time.time()
263+
eprint("getBestEUs start")
221264
for csv_file in csv_files:
222-
getBestEws(csv_file, rows, run_date=run_date, exp_days=exp_days)
223-
265+
getBestEUs(csv_file, rows, run_date=run_date, exp_days=exp_days)
266+
eprint(f"getBestEUs done - {int(time.time() - start_time)}")
224267
if not rows:
225268
eprint("no rows found!")
226269
sys.exit()
227270
# row = rows[0]
228271
# columns = list(row.keys())
229-
df = pd.DataFrame(rows, columns=BEST_EW_COLUMNS)
272+
df = pd.DataFrame(rows, columns=BEST_EW_COLUMNS, )
230273

231274
days = df['days_exp']
232275
print(df.columns)
233276
print("days:", days)
234-
print("fow count:", len(df))
277+
print("row count:", len(df))
235278
days = list(set(list(days.values)))
236279
days.sort()
237280

238-
239-
240281
if out_dir:
241282
original_stdout = sys.stdout # Save a reference to the original standard output
283+
eprint(f"days start - {int(time.time() - start_time)}")
284+
242285
for day in days:
243286
if day < MIN_DAY:
244287
#eprint(f"{day} less than {MIN_DAY}, skipping")
@@ -248,47 +291,32 @@ def getBestEws(stocklist_file, rows, run_date=None, exp_days=None):
248291
continue
249292
logging.info(f"running day: {day}")
250293
df_day = df[df.days_exp == day]
251-
eprint(f"df_day: {len(df_day)} rows")
294+
logging.info(f"df_day: {len(df_day)} rows")
252295
if len(df_day.index) == 0:
253-
eprint("no rows")
296+
logging.info("no rows")
254297
continue # no rows
255-
df_day = df_day[df_day.e_w > MIN_EW]
256-
logging.info(f"df_day pod e_w: {len(df_day)} rows")
257-
258-
df_day = df_day.drop(df_day[df_day.dmu <= MIN_DMU].index)
259-
df_day = df_day.drop(df_day[df_day.dmu <= MIN_DMU].index)
260-
df_day = df_day.drop(df_day[df_day.dmu2 <= MIN_DMU2].index)
261-
# df_day = df_day.drop(df_day[df_day.dme_u <= MIN_DME_U].index)
262-
df_day = df_day.drop(df_day[df_day.dme_w <= MIN_DME_W].index)
263-
df_day = df_day.drop(df_day[df_day.mg <= MIN_MG].index)
264-
for symbol in ODD_DAY_SYMBOLS:
265-
df_day = df_day.drop(df_day[df_day.symbol == symbol].index)
266-
df_day = df_day.sort_values(by="dme_w", ascending=False) # DME_u
267-
298+
df_day = minmaxFilter(df_day)
299+
268300
if len(df_day.index) > 0:
269301
filename = f"{out_dir}/best_ew_{run_date}_{day}.csv"
270302
df_day = df_day.rename(columns=RENAME_COLUMNS)
271303
with open(filename, 'w') as f:
272304
sys.stdout = f # Change the standard output to the file we created.
273305
output = df_day.to_csv(float_format="%.2f")
274306
print(output)
307+
eprint(f"days done - {int(time.time() - start_time)}")
308+
275309
# odd days file
276310
filename = f"{out_dir}/best_ew_{run_date}_index.csv"
277-
df_odd = df[df["symbol"].isin(ODD_DAY_SYMBOLS)]
278-
df_odd = df_odd[df_odd.e_w > MIN_EW]
279-
df_odd = df_odd.drop(df_odd[df_odd.dmu <= MIN_DMU].index)
280-
df_odd = df_odd.drop(df_odd[df_odd.dmu2 <= MIN_DMU2].index)
281-
# df_odd = df_odd.drop(df_odd[df_odd.dme_u <= MIN_DME_U].index)
282-
df_odd = df_odd.drop(df_odd[df_odd.dme_w <= MIN_DME_W].index)
283-
df_odd = df_odd.drop(df_odd[df_odd.mg <= MIN_MG].index)
284-
df_odd = df_odd.drop(df_odd[df_odd["days_exp"] < MIN_DAY].index)
285-
df_odd = df_odd.drop(df_odd[df_odd["days_exp"] > MAX_DAY].index)
286-
df_odd = df_odd.sort_values(by="symbol", ascending=False)
311+
df = pd.DataFrame(rows, columns=BEST_EW_COLUMNS)
312+
df_odd = minmaxFilter(df, use_odd_day_symbols=True)
287313
df_odd = df_odd.rename(columns=RENAME_COLUMNS)
288314
with open(filename, 'w') as f:
289315
sys.stdout = f # Change the standard output to the file we created.
290316
output = df_odd.to_csv(float_format="%.2f")
291317
print(output)
318+
eprint(f"odds done - {int(time.time() - start_time)}")
319+
292320

293321
sys.stdout = original_stdout # Reset the standard output to its original value
294322
else:

opchain/opchain.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
MIN_VAL = -999.0
3030
DEFAULT_DAYS = 45
3131
CSR_CS_DELTA_RANGE = (0.1, 0.17) #was .18
32-
CSR_CB_DELTA_RANGE = (0.005, 0.17)
32+
CSR_CB_DELTA_RANGE = (0.009, 0.17)
3333
PSR_PS_DELTA_RANGE = (0.1, 0.14) #.15
34-
PSR_PB_DELTA_RANGE = (0.005, 0.14)
34+
PSR_PB_DELTA_RANGE = (0.009, 0.14)
3535
USE_PRICE = "mark"
3636

3737
def eprint(*args, **kwargs):
@@ -45,8 +45,9 @@ def get_today():
4545

4646

4747
def get_chains(symbol, run_date=None, dt_min=None, dt_max=None, reload=False):
48-
logging.info(f"get_chains {symbol}, run_date: {run_date}")
48+
logging.info(f"get_chains {symbol}, run_date: {run_date} reload=True")
4949
now = time.time()
50+
logging.info(f"start time: {int(now)}")
5051
if dt_min is None:
5152
# use current time
5253
dt_min = datetime.fromtimestamp(now)
@@ -83,6 +84,7 @@ def get_chains(symbol, run_date=None, dt_min=None, dt_max=None, reload=False):
8384
# params["daysToExpiration"] = 45
8485
req = "https://api.tdameritrade.com/v1/marketdata/chains"
8586
rsp = requests.get(req, params=params, headers=headers)
87+
logging.info(f"making request to tdameritrade: {req}")
8688
if rsp.status_code != 200:
8789
logging.error(f"got bad status code: {rsp.status_code}")
8890
return None
@@ -501,6 +503,8 @@ def get_candidates(contracts, putCall=None, sell_range=None, buy_range=None, day
501503
columns.append(name)
502504

503505
candidate_rows = []
506+
logging.info(f"get_candidates - iteratting over: {len(contracts)} rows")
507+
start = time.time()
504508

505509
for i, b in contracts.iterrows():
506510
if b.daysToExpiration != daysToExpiration:
@@ -513,9 +517,11 @@ def get_candidates(contracts, putCall=None, sell_range=None, buy_range=None, day
513517
logging.debug(f"skipping row {i}, b delta {b.delta} out of range: {buy_range}")
514518
continue
515519

520+
logging.info(f"get_candidates - inner iteration loop: {len(contracts)} rows")
516521
for j, s in contracts.iterrows():
517522
if i == j:
518523
continue
524+
519525
if s.daysToExpiration != daysToExpiration:
520526
logging.debug(f"skipping sell row {j}, daysToExpiration[{s.daysToExpiration}] != {daysToExpiration}")
521527
continue
@@ -564,6 +570,7 @@ def get_candidates(contracts, putCall=None, sell_range=None, buy_range=None, day
564570

565571
#candidates['pom'] = 1 - abs(candidates['s_delta'])
566572
logging.info(f"get_candidates, returning {len(candidates)} candidates from {len(contracts)} contracts")
573+
logging.info(f"time spent for {len(contracts)}: {(time.time() - start):.2f}")
567574
candidates = candidates.sort_values(by="e_w", ascending=False)
568575
return candidates
569576

xetfs.csv

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ $RUT.X
66
$SPX.X
77
SPY
88
$VIX.X
9-
VXX
9+
VXX
10+
EWZ

xstocks.csv

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
AAPL
22
ABBV
3-
ADBE
3+
#ADBE
44
ALGN
55
AMD
66
AMZN
77
CMG
8-
CNC
9-
EWZ
8+
#CNC
109
FB
1110
GOOG
1211
GOOGL
1312
GS
1413
ISRG
15-
KHC
14+
#KHC
1615
LMT
1716
LRCX
1817
LULU
@@ -22,7 +21,7 @@ MS
2221
NFLX
2322
NVDA
2423
SHOP
25-
SIG
24+
#SIG
2625
TSLA
2726
UNH
2827
UVXY

0 commit comments

Comments
 (0)