add otm percentage
This commit is contained in:
parent
8797e61495
commit
b146a93ddb
@ -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:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user