add otm percentage

This commit is contained in:
MuslemRahimi 2024-09-08 16:11:57 +02:00
parent 8797e61495
commit b146a93ddb

View File

@ -83,15 +83,35 @@ def compute_daily_gex(option_data_list, volatility):
daily_gex['date'] = daily_gex['date'].astype(str)
return daily_gex
def summarize_option_chain(option_data_list):
def calculate_otm_percentage(option_data_list):
otm_count = 0
total_options = len(option_data_list)
for option_data in option_data_list:
strike_price = float(option_data['strike_price'])
put_call = option_data['put_call']
stock_price = float(option_data['stock_price']) # Get stock price for this option
# Check if the option is out-of-the-money
if (put_call == 'CALL' and strike_price > stock_price) or (put_call == 'PUT' and strike_price < stock_price):
otm_count += 1
if total_options > 0:
return (otm_count / total_options) * 100
else:
return 0
def summarize_option_chain_with_otm(option_data_list, df_price):
summary_data = []
for option_data in option_data_list:
try:
date = datetime.strptime(option_data['date'], "%Y-%m-%d").date()
expiration_date = datetime.strptime(option_data['date_expiration'], "%Y-%m-%d").date()
open_interest = int(option_data.get('open_interest', 0))
volume = int(option_data.get('volume', 0))
price = float(option_data.get('price', 0))
strike_price = float(option_data.get('strike_price', 0))
put_call = option_data.get('put_call', 'CALL')
sentiment = option_data.get('sentiment', 'NEUTRAL')
@ -102,6 +122,17 @@ def summarize_option_chain(option_data_list):
except (TypeError, ValueError):
premium = 0
# Determine the stock price based on expiration date
if expiration_date > date.today():
stock_price = df_price['close'].iloc[-1] # Latest stock price
else:
# Get the stock price on the option's date
stock_price_row = df_price[df_price['date'] == str(date)]
if not stock_price_row.empty:
stock_price = stock_price_row['close'].values[0]
else:
continue # Skip this option if the price isn't available for the date
# Calculate Bull/Bear/Neutral premiums based on sentiment
if sentiment == 'BULLISH':
bull_premium = premium
@ -116,6 +147,7 @@ def summarize_option_chain(option_data_list):
bear_premium = 0
neutral_premium = premium
# Append option data for later summarization
summary_data.append({
'date': date,
'open_interest': open_interest,
@ -123,38 +155,54 @@ def summarize_option_chain(option_data_list):
'p_vol': volume if put_call == 'PUT' else 0,
'bull_premium': bull_premium,
'bear_premium': bear_premium,
'neutral_premium': neutral_premium
'neutral_premium': neutral_premium,
'put_call': put_call,
'strike_price': strike_price,
'stock_price': stock_price
})
except:
pass
except Exception as e:
print(f"Error processing option data: {e}")
continue
# Summarize by date
df_summary = pd.DataFrame(summary_data)
# Calculate OTM percentage for each day
def calculate_daily_otm(df):
return calculate_otm_percentage(df.to_dict('records')) # Pass the day's options for OTM calculation
# Apply OTM percentage calculation for each day
daily_summary = df_summary.groupby('date').agg(
total_oi=('open_interest', 'sum'),
total_bull_prem=('bull_premium', 'sum'),
total_bear_prem=('bear_premium', 'sum'),
total_neutral_prem=('neutral_premium', 'sum'),
c_vol=('c_vol', 'sum'),
p_vol=('p_vol', 'sum')
p_vol=('p_vol', 'sum'),
).reset_index()
# Calculate Bull/Bear ratio
try:
daily_summary['bear_ratio'] = round(daily_summary['total_bear_prem'] / (daily_summary['total_bull_prem']+daily_summary['total_bear_prem']+daily_summary['total_neutral_prem']) * 100, 2)
daily_summary['bull_ratio'] = round(daily_summary['total_bull_prem'] / (daily_summary['total_bull_prem']+daily_summary['total_bear_prem']+daily_summary['total_neutral_prem']) * 100, 2)
daily_summary['neutral_ratio'] = round(daily_summary['total_neutral_prem'] / (daily_summary['total_bull_prem']+daily_summary['total_bear_prem']+daily_summary['total_neutral_prem']) * 100, 2)
except:
daily_summary['bear_ratio'] = None
daily_summary['bull_ratio'] = None
daily_summary['neutral_ratio'] = None
# Calculate OTM percentage for each date and assign it to the daily_summary
daily_summary['otm_ratio'] = df_summary.groupby('date').apply(lambda df: round(calculate_otm_percentage(df.to_dict('records')), 1)).values
daily_summary['total_volume'] = round(daily_summary['c_vol'] + daily_summary['p_vol'],2)
daily_summary['total_neutral_prem'] = round(daily_summary['total_neutral_prem'],2)
# Calculate Bull/Bear/Neutral ratios
try:
total_prem = daily_summary['total_bull_prem'] + daily_summary['total_bear_prem'] + daily_summary['total_neutral_prem']
daily_summary['bull_ratio'] = round(daily_summary['total_bull_prem'] / total_prem * 100, 2)
daily_summary['bear_ratio'] = round(daily_summary['total_bear_prem'] / total_prem * 100, 2)
daily_summary['neutral_ratio'] = round(daily_summary['total_neutral_prem'] / total_prem * 100, 2)
except ZeroDivisionError:
daily_summary['bull_ratio'] = None
daily_summary['bear_ratio'] = None
daily_summary['neutral_ratio'] = None
# Calculate total volume (call + put) and format other fields
daily_summary['total_volume'] = round(daily_summary['c_vol'] + daily_summary['p_vol'], 2)
daily_summary['total_neutral_prem'] = round(daily_summary['total_neutral_prem'], 2)
daily_summary['date'] = daily_summary['date'].astype(str)
daily_summary = daily_summary.sort_values(by='date', ascending=False)
# Return the summarized dataframe
return daily_summary
@ -203,7 +251,7 @@ query_template = """
"""
# Process each symbol
for ticker in total_symbols:
for ticker in ['GME']: #total_symbols:
try:
query = query_template.format(ticker=ticker)
df_price = pd.read_sql_query(query, stock_con if ticker in stock_symbols else etf_con, params=(start_date_str, end_date_str)).round(2)
@ -212,11 +260,12 @@ for ticker in total_symbols:
volatility = calculate_volatility(df_price)
ticker_data = get_data(ticker)
daily_option_chain = summarize_option_chain(ticker_data)
daily_option_chain = summarize_option_chain_with_otm(ticker_data, df_price)
daily_option_chain = daily_option_chain.merge(df_price[['date', 'changesPercentage']], on='date', how='inner')
if not daily_option_chain.empty:
save_json(ticker, daily_option_chain.to_dict('records'), 'json/options-chain/companies')
daily_gex = compute_daily_gex(ticker_data, volatility)
daily_gex = daily_gex.merge(df_price[['date', 'close']], on='date', how='inner')
if not daily_gex.empty: