| Overall Statistics |
|
Total Trades 9 Average Win 24.92% Average Loss 0% Compounding Annual Return 6.278% Drawdown 29.300% Expectancy 0 Net Profit 122.988% Sharpe Ratio 0.429 Probabilistic Sharpe Ratio 0.438% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.047 Beta 0.07 Annual Standard Deviation 0.117 Annual Variance 0.014 Information Ratio 0.039 Tracking Error 0.357 Treynor Ratio 0.717 Total Fees $150.25 Estimated Strategy Capacity $2000.00 Lowest Capacity Asset NOK YP8G69SI9YO6|NOK R735QTJ8XC9X |
#region imports
from AlgorithmImports import *
#endregion
Balance = 10000
Minimum_Expiry = 720
Maximum_Expiry = 90
Max_Option_Price = 0.75
Min_Option_Price = 0.45
Profit_Taking = 1.8
class NOKLeapsBreakout(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetEndDate(2023, 3, 1)
self.SetCash(Balance)
equity = self.AddEquity("NOK", Resolution.Minute)
equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.equity = equity.Symbol
self.SetBenchmark(self.equity)
option = self.AddOption("NOK", Resolution.Minute)
option.SetFilter(-2, 1, timedelta(Minimum_Expiry), timedelta(99999))
self.Schedule.On(self.DateRules.EveryDay(self.equity), \
self.TimeRules.AfterMarketOpen(self.equity, 30), \
self.Plotting)
def OnData(self,data):
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
if option_invested:
if self.Time + timedelta(Maximum_Expiry) > option_invested[0].ID.Date:
self.Liquidate(option_invested[0], "Too close to expiration")
last_o_id = self.Transactions.LastOrderId
self.Debug (f"| {self.Time} [+]--- Liquidate @ {str(self.Transactions.GetOrderTicket(last_o_id).AverageFillPrice)} || Stock @ {str(self.Portfolio[self.equity].Price)}|| Loss @ {str(self.Portfolio[option_invested[0]].LastTradeProfit)}")
self.Debug (f"| {self.Time} [-]--- REASON: || <{(Maximum_Expiry)} DTE | {(option_invested[0].ID.Date - self.Time).days} DTE")
return
if not option_invested:
for i in data.OptionChains:
chains = i.Value
self.BuyCall(chains)
# Buy options - Call
def BuyCall(self,chains):
expiry = sorted(chains,key = lambda x: x.Expiry, reverse=True)[0].Expiry
calls = [i for i in chains if i.Expiry == expiry and i.Right == OptionRight.Call and i.AskPrice < Max_Option_Price and i.AskPrice > Min_Option_Price]
call_contracts = sorted(calls,key = lambda x: abs(x.Strike - x.UnderlyingLastPrice))
if len(call_contracts) == 0:
return
self.call = call_contracts[0]
self.SetHoldings(self.call.Symbol, 0.3)
quantity = self.Portfolio[self.call.Symbol].Quantity # <-- quantity is zero and the following orders will be invalid
self.LimitOrder(self.call.Symbol, -quantity, (self.call.AskPrice * Profit_Taking))
self.Debug ("\r+-------------")
self.Debug (f"| {self.Time} [+]--- BUY {str(self.call)} || Stock @ {str(self.call.UnderlyingLastPrice)}")
self.Debug(f"Order Quantity filled: {self.Portfolio[self.call.Symbol].Quantity}; Fill price: {self.Portfolio[self.call.Symbol].AveragePrice}")
self.Log("Bought NOK Options")
def Plotting(self):
# plot underlying's price
self.Plot("Data Chart", self.equity, self.Securities[self.equity].Close)
# plot strike of call option
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
if option_invested:
self.Plot("Data Chart", "strike", option_invested[0].ID.StrikePrice)
# plot Maximum against NOK Price - lookback 15 days
self.Plot("My Indicators", "Nok Price", self.Securities[self.equity].Close)
def OnOrderEvent(self, orderEvent):
order = self.Transactions.GetOrderById(orderEvent.OrderId)
# Cancel remaining order if limit order or stop loss order is executed
if order.Status == OrderStatus.Filled:
if order.Type == OrderType.Limit or OrderType.StopMarket:
self.Transactions.CancelOpenOrders(order.Symbol)
if order.Status == OrderStatus.Filled and order.Type == OrderType.Limit:
self.Debug(f"{self.Time} [+]--- SELL {str(order.Quantity)} || Price @ {str(order.LimitPrice)}|| Profit @ {str(self.Portfolio[self.call.Symbol].LastTradeProfit)}")
if order.Status == OrderStatus.Canceled:
self.Log(str(orderEvent))
# Liquidate before options are exercised
if order.Type == OrderType.OptionExercise:
self.Liquidate()