| Overall Statistics |
|
Total Orders 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Start Equity 100000 End Equity 100000 Net Profit 0% Sharpe Ratio 0 Sortino Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% Drawdown Recovery 0 |
from AlgorithmImports import *
import json
from collections import defaultdict
class GammaExposureAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2025, 8, 5)
self.SetEndDate(2025, 8, 5)
self.SetCash(100000)
self.spx = self.AddIndex("SPX", Resolution.Minute).Symbol
option = self.AddIndexOption(self.spx, "SPXW", Resolution.Minute)
option.SetFilter(lambda x: x.IncludeWeeklys().Strikes(-100, 100).Expiration(0, 7))
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(10, 30), self.CalculateGEX)
self.object_store_key = f"gex_test_{self.Time.strftime('%Y%m%d')}"
def OnData(self, data):
pass
def CalculateGEX(self):
spot = self.Securities[self.spx].Price
if spot == 0:
self.Log("ERROR: No SPX price")
return
chains = self.CurrentSlice.OptionChains
if not chains:
self.Log("ERROR: No option chains")
return
gex_data = defaultdict(lambda: {'call_gex': 0, 'put_gex': 0, 'total_gex': 0})
total_gex = contracts = 0
today = self.Time.date()
for chain in chains.values():
for c in chain:
if c.Expiry.date() != today or not c.Greeks or c.Greeks.Gamma == 0:
continue
strike = float(c.Strike)
gamma = c.Greeks.Gamma
oi = getattr(c, 'OpenInterest', None) or c.Volume or 1000
contract_gex = gamma * oi * 100 * (spot ** 2)
adjusted_gex = -contract_gex if c.Right == OptionRight.Call else contract_gex
if c.Right == OptionRight.Call:
gex_data[strike]['call_gex'] += adjusted_gex
else:
gex_data[strike]['put_gex'] += adjusted_gex
gex_data[strike]['total_gex'] += adjusted_gex
total_gex += adjusted_gex
contracts += 1
self.Log(f"SPX: {spot}, Contracts: {contracts}, Total GEX: ${total_gex:,.0f}")
self.ExportData(gex_data, spot, total_gex)
def ExportData(self, gex_data, spot, total_gex):
strikes = sorted(gex_data.keys())
export_data = {
'metadata': {
'timestamp': self.Time.isoformat(),
'spot_price': float(spot),
'total_gamma_exposure': float(total_gex),
'num_strikes': len(strikes)
},
'strike_data': [{
'strike': float(s),
'total_gex': float(gex_data[s]['total_gex']),
'call_gex': float(gex_data[s]['call_gex']),
'put_gex': float(gex_data[s]['put_gex']),
'distance_from_spot': float(s - spot)
} for s in strikes]
}
try:
success = self.ObjectStore.Save(self.object_store_key, json.dumps(export_data))
self.Log(f"{'✓' if success else '✗'} Export: {len(strikes)} strikes")
except Exception as e:
self.Log(f"Export error: {e}")
# Log top 3 GEX strikes
top_strikes = sorted(gex_data.items(), key=lambda x: abs(x[1]['total_gex']), reverse=True)[:3]
for i, (strike, data) in enumerate(top_strikes):
self.Log(f"{i+1}. {strike}: ${data['total_gex']:,.0f}")
def OnEndOfAlgorithm(self):
self.Log(f"Complete. ObjectStore key: {self.object_store_key}")