diff --git a/app/cron_options_net_flow.py b/app/cron_options_net_flow.py index 46559e7..bed8462 100644 --- a/app/cron_options_net_flow.py +++ b/app/cron_options_net_flow.py @@ -24,82 +24,81 @@ def calculate_moving_average(data, window_size): moving_avg = (cumsum[window_size - 1:] - np.concatenate(([0], cumsum[:-window_size]))) / window_size return moving_avg.tolist() -def calculate_net_flow(data, window_size=20): - date_data = defaultdict(lambda: {'price': [], 'netCall': 0, 'netPut': 0}) +def calculate_net_flow(data): + date_data = defaultdict(lambda: {'price': [], 'netCall': 0, 'netPut': 0}) for item in data: - date = item['date'] + date_str = item['date'] + time_str = item['time'] + datetime_str = f"{date_str} {time_str}" + + # Parse the combined date and time into a datetime object + date_time = datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S') + try: premium = float(item['cost_basis']) - date_data[date]['price'].append(float(item['underlying_price'])) - #date_data[date]['volume'] += volume - + date_data[date_time]['price'].append(round(float(item['underlying_price']), 2)) if item['put_call'] == 'CALL': if item['execution_estimate'] == 'AT_ASK': - date_data[date]['netCall'] += premium + date_data[date_time]['netCall'] += premium elif item['execution_estimate'] == 'AT_BID': - date_data[date]['netCall'] -= premium + date_data[date_time]['netCall'] -= premium elif item['put_call'] == 'PUT': if item['execution_estimate'] == 'AT_ASK': - date_data[date]['netPut'] -= premium + date_data[date_time]['netPut'] -= premium elif item['execution_estimate'] == 'AT_BID': - date_data[date]['netPut'] += premium + date_data[date_time]['netPut'] += premium except: pass - #volume = int(item['volume']) # Calculate average underlying price and format the results result = [] - for date, values in date_data.items(): - avg_price = sum(values['price']) / len(values['price']) - #volume = values['volume'] - - # Change sign of volume if netPut > netCall - #if values['netPut'] > values['netCall']: - # volume = -volume - + for date_time, values in date_data.items(): result.append({ - 'date': date, - 'price': round(avg_price, 2), + 'date': date_time.strftime('%Y-%m-%d %H:%M:%S'), + 'price': sum(values['price']) / len(values['price']) if values['price'] else 0, 'netCall': int(values['netCall']), 'netPut': int(values['netPut']), - #'volume': int(volume) }) - sorted_data = sorted(result, key=lambda x: datetime.strptime(x['date'], '%Y-%m-%d')) - - # Calculate moving averages - netCall_values = [item['netCall'] for item in sorted_data] - netPut_values = [item['netPut'] for item in sorted_data] - - netCall_ma = calculate_moving_average(netCall_values, window_size) - netPut_ma = calculate_moving_average(netPut_values, window_size) - - # Add moving averages to the result and remove None values - filtered_data = [] + sorted_data = sorted(result, key=lambda x: datetime.strptime(x['date'], '%Y-%m-%d %H:%M:%S')) - # Add moving averages to the result - filtered_data = [] - for i, item in enumerate(sorted_data): - if i >= window_size - 1: - item['netCall'] = int(netCall_ma[i - window_size + 1]) - item['netPut'] = int(netPut_ma[i - window_size + 1]) - filtered_data.append(item) + # Compute 30-minute interval averages + interval_data = defaultdict(lambda: {'price': [], 'netCall': [], 'netPut': []}) + for item in sorted_data: + date_time = datetime.strptime(item['date'], '%Y-%m-%d %H:%M:%S') + interval_start = date_time.replace(minute=date_time.minute // 120 * 120, second=0) + + interval_data[interval_start]['price'].append(item['price']) + interval_data[interval_start]['netCall'].append(item['netCall']) + interval_data[interval_start]['netPut'].append(item['netPut']) - return filtered_data + # Calculate averages for each 30-minute interval + averaged_data = [] + for interval_start, values in interval_data.items(): + if values['price']: + averaged_data.append({ + 'date': interval_start.strftime('%Y-%m-%d %H:%M:%S'), + #'price': sum(values['price']) / len(values['price']) , + 'netCall': sum(values['netCall']) if values['netCall'] else 0, + 'netPut': sum(values['netPut']) if values['netPut'] else 0, + }) + # Sort the averaged data by interval start time + averaged_data.sort(key=lambda x: datetime.strptime(x['date'], '%Y-%m-%d %H:%M:%S')) + return averaged_data def get_data(symbol): try: end_date = date.today() - start_date = end_date - timedelta(200) + start_date = end_date - timedelta(10) end_date_str = end_date.strftime('%Y-%m-%d') start_date_str = start_date.strftime('%Y-%m-%d') res_list = [] - for page in range(0, 100): + for page in range(0, 1000): try: data = fin.options_activity(company_tickers=symbol, page=page, pagesize=1000, date_from=start_date_str, date_to=end_date_str) data = ujson.loads(fin.output(data))['option_activity'] @@ -107,8 +106,7 @@ def get_data(symbol): except: break - res_filtered = [{key: value for key, value in item.items() if key in ['ticker','date','execution_estimate', 'underlying_price', 'put_call', 'cost_basis']} for item in res_list] - + res_filtered = [{key: value for key, value in item.items() if key in ['ticker','time','date','execution_estimate', 'underlying_price', 'put_call', 'cost_basis']} for item in res_list] #Save raw data for each ticker for options page stack bar chart ticker_filtered_data = [entry for entry in res_filtered if entry['ticker'] == symbol] @@ -126,7 +124,7 @@ def get_data(symbol): try: stock_con = sqlite3.connect('stocks.db') stock_cursor = stock_con.cursor() - stock_cursor.execute("SELECT DISTINCT symbol FROM stocks WHERE symbol NOT LIKE '%.%'") + stock_cursor.execute("SELECT DISTINCT symbol FROM stocks WHERE marketCap >500E6 AND symbol NOT LIKE '%.%'") stock_symbols = [row[0] for row in stock_cursor.fetchall()] etf_con = sqlite3.connect('etf.db')