Overall Statistics |
Total Trades 800 Average Win 0.48% Average Loss -0.22% Compounding Annual Return 55.958% Drawdown 7.900% Expectancy 0.553 Net Profit 59.352% Sharpe Ratio 3.699 Probabilistic Sharpe Ratio 96.885% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 2.24 Alpha 0.373 Beta 0.066 Annual Standard Deviation 0.099 Annual Variance 0.01 Information Ratio 2.188 Tracking Error 0.21 Treynor Ratio 5.584 Total Fees $0.00 Estimated Strategy Capacity $2000.00 Lowest Capacity Asset SPXW 323M70XAFNHIM|SPX 31 |
from AlgorithmImports import * from collections import deque import statistics as stats import config class PremiumThresholdAdjuster(): def __init__(self, algorithm): self.algorithm = algorithm self.Avg_Premium_Length = config.PREMIUM_ADJUST_LENGTH self.Avg_Premium_1_Queue = deque(maxlen=self.Avg_Premium_Length) self.Avg_Premium_15_Queue = deque(maxlen=self.Avg_Premium_Length) self.Avg_Premium_20_Queue = deque(maxlen=self.Avg_Premium_Length) self.Avg_Premium_25_Queue = deque(maxlen=self.Avg_Premium_Length) self.Avg_Premium_30_Queue = deque(maxlen=self.Avg_Premium_Length) self.Avg_Premium_1 = None self.Avg_Premium_15 = None self.Avg_Premium_20 = None self.Avg_Premium_25 = None self.Avg_Premium_30 = None self.One_Premium = None self.One_Five_Premium = None self.Two_Premium = None self.Two_Five_Premium = None self.Three_Premium = None def receive_condors(self, c_1, c_1_5, c_2, c_2_5, c_3): self.One_Premium = c_1 self.One_Five_Premium = c_1_5 self.Two_Premium = c_2 self.Two_Five_Premium = c_2_5 self.Three_Premium = c_3 def return_premium_today(self, range_today): if range_today == 0.01: if self.One_Premium is not None: return self.One_Premium else: return config.FIXED_PREMIUM_1 elif range_today == 0.015: if self.One_Five_Premium is not None: return self.One_Five_Premium else: return config.FIXED_PREMIUM_1_5 elif range_today == 0.02: if self.Two_Premium is not None: return self.Two_Premium else: return config.FIXED_PREMIUM_2 elif range_today == 0.025: if self.Two_Five_Premium is not None: return self.Two_Five_Premium else: return config.FIXED_PREMIUM_2_5 elif range_today == 0.03: if self.Three_Premium is not None: return self.Three_Premium else: return config.FIXED_PREMIUM_3 def Update_Highest_Premiums(self): if self.Two_Premium is not None: premium = self.Two_Premium.Calculate_Premium() if premium > self.Two_Premium.Highest_Premium: self.Two_Premium.Highest_Premium = premium if self.Two_Five_Premium is not None: premium = self.Two_Five_Premium.Calculate_Premium() if premium > self.Two_Five_Premium.Highest_Premium: self.Two_Five_Premium.Highest_Premium = premium if self.One_Five_Premium is not None: premium = self.One_Five_Premium.Calculate_Premium() if premium > self.One_Five_Premium.Highest_Premium: self.One_Five_Premium.Highest_Premium = premium if self.Three_Premium is not None: premium = self.Three_Premium.Calculate_Premium() if premium > self.Three_Premium.Highest_Premium: self.Three_Premium.Highest_Premium = premium def Append_1(self, premium): self.Avg_Premium_1_Queue.appendleft(premium) if len(self.Avg_Premium_1_Queue) == self.Avg_Premium_Length: self.Avg_Premium_1 = sum(self.Avg_Premium_1_Queue) / len(self.Avg_Premium_1_Queue) self.algorithm.Plot("Average Premium 1%", "Premium", self.Avg_Premium_1) def Append_15(self, premium): self.Avg_Premium_15_Queue.appendleft(premium) if len(self.Avg_Premium_15_Queue) == self.Avg_Premium_Length: self.Avg_Premium_15 = sum(self.Avg_Premium_15_Queue) / len(self.Avg_Premium_15_Queue) self.algorithm.Plot("Average Premium 1.5%", "Premium", self.Avg_Premium_15) def Append_20(self, premium): self.Avg_Premium_20_Queue.appendleft(premium) if len(self.Avg_Premium_20_Queue) == self.Avg_Premium_Length: self.Avg_Premium_20 = sum(self.Avg_Premium_20_Queue) / len(self.Avg_Premium_20_Queue) self.algorithm.Plot("Average Premium 2%", "Premium", self.Avg_Premium_20) def Append_25(self, premium): self.Avg_Premium_25_Queue.appendleft(premium) if len(self.Avg_Premium_25_Queue) == self.Avg_Premium_Length: self.Avg_Premium_25 = sum(self.Avg_Premium_25_Queue) / len(self.Avg_Premium_25_Queue) self.algorithm.Plot("Average Premium 2.5%", "Premium", self.Avg_Premium_25) def Append_30(self, premium): self.Avg_Premium_30_Queue.appendleft(premium) if len(self.Avg_Premium_30_Queue) == self.Avg_Premium_Length: self.Avg_Premium_30 = sum(self.Avg_Premium_30_Queue) / len(self.Avg_Premium_30_Queue) self.algorithm.Plot("Average Premium 3%", "Premium", self.Avg_Premium_30)
from AlgorithmImports import * from collections import deque import config class AvgDown(): def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.use_avg_down = config.USE_AVG_DOWN self.avg_down_mode = config.AVG_DOWN_MODE self.fixed_avg_down_premium = config.FIXED_AVG_DOWN_PREMIUM self.avg_down_percentage = config.AVG_DOWN_PERCENTAGE self.avg_down_x_times = config.AVG_DOWN_X_TIMES self.use_most_recent_entry = config.USE_MOST_RECENT_ENTRY self.pivot_queue = deque(maxlen=3) self.entered_condor = None self.entered_key = None self.avg_down_counter = 0 self.first_entry = None def append_pivot(self): if self.entered_condor is not None: self.entered_condor.Calculate_Premium() self.pivot_queue.appendleft(self.entered_condor.Premium) def check_avg_down(self): if self.use_avg_down and self.avg_down_counter < self.avg_down_x_times: if self.avg_down_mode == "PERCENTAGE": if self.check_percentage_avg_down(): return True else: return False elif self.avg_down_mode == "PIVOT POINT": if self.check_pivot_avg_down(): return True else: return False elif self.avg_down_mode == "PERCENTAGE PIVOT POINT": if self.check_percentage_avg_down() and self.check_pivot_avg_down(): return True else: return False elif self.avg_down_mode == "FIXED": if self.entered_condor.Premium >= self.fixed_avg_down_premium: return True else: return False elif self.avg_down_mode == "FIXED PIVOT POINT": if self.entered_condor.Premium >= self.fixed_avg_down_premium and self.check_pivot_avg_down(): return True else: return False else: return False else: return False def check_percentage_avg_down(self): if not self.use_most_recent_entry: self.entered_condor.Calculate_Premium() if self.entered_condor.Premium >= self.first_entry * self.avg_down_percentage: return True else: return False else: self.entered_condor.Calculate_Premium() if self.entered_condor.Premium >= self.entered_condor.Entry_Premium * self.avg_down_percentage: return True else: return False def check_pivot_avg_down(self): if len(self.pivot_queue) == 3 and self.pivot_queue[0] < self.pivot_queue[1] > self.pivot_queue[2]: return True else: return False def reset(self): self.use_avg_down = config.USE_AVG_DOWN self.avg_down_mode = config.AVG_DOWN_MODE self.fixed_avg_down_premium = config.FIXED_AVG_DOWN_PREMIUM self.avg_down_percentage = config.AVG_DOWN_PERCENTAGE self.avg_down_x_times = config.AVG_DOWN_X_TIMES self.use_most_recent_entry = config.USE_MOST_RECENT_ENTRY self.pivot_queue = deque(maxlen=3) self.entered_condor = None self.entered_key = None self.avg_down_counter = 0 self.first_entry = None
#region imports from AlgorithmImports import * USE_POWELL = True POWELL = [ #datetime(2021, 1, 14).strftime("%Y%-m%-d"), #Powell 12:30 # #datetime(2021, 2, 10).strftime("%Y%-m%-d"), #Powell 14:00 # datetime(2021, 2, 23).strftime("%Y%-m%-d"), #Powell 10:00 datetime(2021, 2, 24).strftime("%Y%-m%-d"), #Powell 10:00 #datetime(2021, 3, 4).strftime("%Y%-m%-d"), #Powell 12:05 # datetime(2021, 3, 22).strftime("%Y%-m%-d"), #Powell 08:00 datetime(2021, 3, 23).strftime("%Y%-m%-d"), #Powell 11:00 datetime(2021, 3, 24).strftime("%Y%-m%-d"), #Powell 09:00 datetime(2021, 4, 8).strftime("%Y%-m%-d"), #Powell 11:00 datetime(2021, 4, 14).strftime("%Y%-m%-d"), #Powell 11:00 #datetime(2021, 5, 3).strftime("%Y%-m%-d"), #Powell 13:20 # datetime(2021, 6, 4).strftime("%Y%-m%-d"), #Powell 06:00 #datetime(2021, 6, 22).strftime("%Y%-m%-d"), #Powell 13:00 # datetime(2021, 7, 14).strftime("%Y%-m%-d"), #Powell 11:00 datetime(2021, 7, 15).strftime("%Y%-m%-d"), #Powell 08:30 #datetime(2021, 8, 17).strftime("%Y%-m%-d"), #Powell 12:30 # datetime(2021, 8, 27).strftime("%Y%-m%-d"), #Powell 09:00 datetime(2021, 9, 24).strftime("%Y%-m%-d"), #Powell 09:00 datetime(2021, 9, 28).strftime("%Y%-m%-d"), #Powell 09:00 datetime(2021, 9, 29).strftime("%Y%-m%-d"), #Powell 09:45 datetime(2021, 10, 22).strftime("%Y%-m%-d"), #Powell 10:00 datetime(2021, 11, 8).strftime("%Y%-m%-d"), #Powell 10:30 datetime(2021, 11, 9).strftime("%Y%-m%-d"), #Powell 9:00 # datetime(2021, 11, 29).strftime("%Y%-m%-d"), #Powell 15:05 # datetime(2021, 11, 30).strftime("%Y%-m%-d"), #Powell 10:00 datetime(2021, 12, 1).strftime("%Y%-m%-d"), #Powell 10:00 datetime(2022, 1, 11).strftime("%Y%-m%-d"), #Powell 10:00 datetime(2022, 3, 2).strftime("%Y%-m%-d"), #Powell 10:00 datetime(2022, 3, 3).strftime("%Y%-m%-d"), #Powell 10:00 datetime(2022, 3, 21).strftime("%Y%-m%-d"), #Powell 11:00 datetime(2022, 3, 23).strftime("%Y%-m%-d"), #Powell 07:00 datetime(2022, 4, 21).strftime("%Y%-m%-d"), #Powell 10:00 # datetime(2022, 5, 17).strftime("%Y%-m%-d"), #Powell 13:00 # datetime(2022, 5, 24).strftime("%Y%-m%-d"), #Powell 11:20 datetime(2022, 6, 17).strftime("%Y%-m%-d"), #Powell 07:45 datetime(2022, 6, 22).strftime("%Y%-m%-d"), #Powell 08:30 datetime(2022, 6, 23).strftime("%Y%-m%-d"), #Powell 09:00 datetime(2022, 6, 29).strftime("%Y%-m%-d"), #Powell 08:00 datetime(2022, 8 ,26).strftime("%Y%-m%-d"), #Powell 09:00 datetime(2022, 9, 8).strftime("%Y%-m%-d"), #Powell 08:10 # datetime(2022, 9, 23).strftime("%Y%-m%-d"), #Powell 13:00 # datetime(2022, 9, 27).strftime("%Y%-m%-d"), #Powell 06:30 datetime(2022, 9, 28).strftime("%Y%-m%-d"), #Powell 09:15 #datetime(2022, 11, 30).strftime("%Y%-m%-d"), #Powell 13:30 # ] USE_POWELL_NEXTDAY = True POWELL_NEXTDAY = [ datetime(2021, 1, 15).strftime("%Y%-m%-d"), #DayAfterPowell datetime(2021, 2, 11).strftime("%Y%-m%-d"), #DAP datetime(2021, 3, 5).strftime("%Y%-m%-d"), #DAP datetime(2021, 3, 25).strftime("%Y%-m%-d"), #DAP datetime(2021, 4, 9).strftime("%Y%-m%-d"), #DAP datetime(2021, 4, 15).strftime("%Y%-m%-d"), #DAP datetime(2021, 5, 4).strftime("%Y%-m%-d"), #DAP datetime(2021, 6, 5).strftime("%Y%-m%-d"), #DAP datetime(2021, 6, 23).strftime("%Y%-m%-d"), #DAP datetime(2021, 7, 16).strftime("%Y%-m%-d"), #DAP datetime(2021, 9, 30).strftime("%Y%-m%-d"), #DAP datetime(2021, 11, 10).strftime("%Y%-m%-d"), #DAP datetime(2021, 12, 2).strftime("%Y%-m%-d"), #DAP datetime(2022, 1, 12).strftime("%Y%-m%-d"), #DAP datetime(2022, 3, 4).strftime("%Y%-m%-d"), #DAP datetime(2022, 3, 22).strftime("%Y%-m%-d"), #DAP datetime(2022, 3, 24).strftime("%Y%-m%-d"), #DAP datetime(2022, 4, 22).strftime("%Y%-m%-d"), #DAP datetime(2022, 5, 17).strftime("%Y%-m%-d"), #DAP datetime(2022, 5, 25).strftime("%Y%-m%-d"), #DAP datetime(2022, 6, 24).strftime("%Y%-m%-d"), #DAP datetime(2022, 8, 27).strftime("%Y%-m%-d"), #DAP datetime(2022, 9, 9).strftime("%Y%-m%-d"), #DAP datetime(2022, 9, 29).strftime("%Y%-m%-d"), #DAP datetime(2022, 12, 1).strftime("%Y%-m%-d"), #DAP ] USE_FED_INTEREST_RATE_DECISION = False FED_INTEREST_RATE_DECISION = [ datetime(2021, 1, 27).strftime("%Y%-m%-d"), datetime(2021, 3, 17).strftime("%Y%-m%-d"), datetime(2021, 4, 28).strftime("%Y%-m%-d"), datetime(2021, 6, 16).strftime("%Y%-m%-d"), datetime(2021, 7, 28).strftime("%Y%-m%-d"), datetime(2021, 9, 22).strftime("%Y%-m%-d"), datetime(2021, 11, 3).strftime("%Y%-m%-d"), datetime(2021, 12, 15).strftime("%Y%-m%-d"), datetime(2022, 1, 26).strftime("%Y%-m%-d"), datetime(2022, 3, 16).strftime("%Y%-m%-d"), datetime(2022, 5, 4).strftime("%Y%-m%-d"), datetime(2022, 6, 15).strftime("%Y%-m%-d"), datetime(2022, 7, 27).strftime("%Y%-m%-d"), datetime(2022, 9, 21).strftime("%Y%-m%-d"), datetime(2022, 11, 2).strftime("%Y%-m%-d"), datetime(2022, 12, 14).strftime("%Y%-m%-d"), ] USE_FED_INTEREST_RATE_DECISION_NEXTDAY = False FED_INTEREST_RATE_DECISION_NEXTDAY = [ datetime(2021, 1, 28).strftime("%Y%-m%-d"), datetime(2021, 3, 18).strftime("%Y%-m%-d"), datetime(2021, 4, 29).strftime("%Y%-m%-d"), datetime(2021, 6, 17).strftime("%Y%-m%-d"), datetime(2021, 7, 29).strftime("%Y%-m%-d"), datetime(2021, 9, 23).strftime("%Y%-m%-d"), datetime(2021, 11, 4).strftime("%Y%-m%-d"), datetime(2021, 12, 16).strftime("%Y%-m%-d"), datetime(2022, 1, 27).strftime("%Y%-m%-d"), datetime(2022, 3, 17).strftime("%Y%-m%-d"), datetime(2022, 5, 5).strftime("%Y%-m%-d"), datetime(2022, 6, 17).strftime("%Y%-m%-d"), datetime(2022, 7, 28).strftime("%Y%-m%-d"), datetime(2022, 9, 22).strftime("%Y%-m%-d"), datetime(2022, 11, 3).strftime("%Y%-m%-d"), datetime(2022, 12, 15).strftime("%Y%-m%-d"), ] USE_FOMC_MEETINGS_FIRSTDAY = False FOMC_MEETINGS_FIRSTDAY = [ datetime(2021, 1, 26).strftime("%Y%-m%-d"), datetime(2021, 3, 16).strftime("%Y%-m%-d"), datetime(2021, 4, 27).strftime("%Y%-m%-d"), datetime(2021, 6, 16).strftime("%Y%-m%-d"), datetime(2021, 7, 27).strftime("%Y%-m%-d"), datetime(2021, 9, 21).strftime("%Y%-m%-d"), datetime(2021, 11, 2).strftime("%Y%-m%-d"), datetime(2021, 12, 14).strftime("%Y%-m%-d"), datetime(2022, 1, 25).strftime("%Y%-m%-d"), datetime(2022, 3, 15).strftime("%Y%-m%-d"), datetime(2022, 5, 3).strftime("%Y%-m%-d"), datetime(2022, 6, 14).strftime("%Y%-m%-d"), datetime(2022, 7, 26).strftime("%Y%-m%-d"), datetime(2022, 9, 20).strftime("%Y%-m%-d"), datetime(2022, 11, 1).strftime("%Y%-m%-d"), datetime(2022, 12, 13).strftime("%Y%-m%-d"), ] USE_FOMC_MEETINGS = True FOMC_MEETINGS = [ datetime(2021, 1, 27).strftime("%Y%-m%-d"), datetime(2021, 3, 17).strftime("%Y%-m%-d"), datetime(2021, 4, 28).strftime("%Y%-m%-d"), datetime(2021, 6, 15).strftime("%Y%-m%-d"), datetime(2021, 7, 28).strftime("%Y%-m%-d"), datetime(2021, 9, 22).strftime("%Y%-m%-d"), datetime(2021, 11, 3).strftime("%Y%-m%-d"), datetime(2021, 12, 15).strftime("%Y%-m%-d"), datetime(2022, 1, 26).strftime("%Y%-m%-d"), datetime(2022, 3, 16).strftime("%Y%-m%-d"), datetime(2022, 5, 4).strftime("%Y%-m%-d"), datetime(2022, 6, 15).strftime("%Y%-m%-d"), datetime(2022, 7, 27).strftime("%Y%-m%-d"), datetime(2022, 9 ,21).strftime("%Y%-m%-d"), datetime(2022, 11, 2).strftime("%Y%-m%-d"), datetime(2022, 12, 14).strftime("%Y%-m%-d"), ] USE_FOMC_MINUTES = False FOMC_MINUTES = [ datetime(2021, 1 ,6).strftime("%Y%-m%-d"), datetime(2021, 2 ,17).strftime("%Y%-m%-d"), datetime(2021, 4 ,7).strftime("%Y%-m%-d"), datetime(2021, 5 ,19).strftime("%Y%-m%-d"), datetime(2021, 7 ,7).strftime("%Y%-m%-d"), datetime(2021, 8 ,18).strftime("%Y%-m%-d"), datetime(2021, 10 ,13).strftime("%Y%-m%-d"), datetime(2021, 11 ,24).strftime("%Y%-m%-d"), datetime(2022, 1 ,5).strftime("%Y%-m%-d"), datetime(2022, 2 ,16).strftime("%Y%-m%-d"), datetime(2022, 4, 6).strftime("%Y%-m%-d"), datetime(2022, 5, 25).strftime("%Y%-m%-d"), datetime(2022, 7, 6).strftime("%Y%-m%-d"), datetime(2022, 8, 17).strftime("%Y%-m%-d"), datetime(2022, 10, 12).strftime("%Y%-m%-d"), datetime(2022, 11, 23).strftime("%Y%-m%-d"), ] USE_CPI = True CPI = [ datetime(2021, 1, 13).strftime("%Y%-m%-d"), datetime(2021, 2, 10).strftime("%Y%-m%-d"), datetime(2021, 3, 10).strftime("%Y%-m%-d"), datetime(2021, 4, 13).strftime("%Y%-m%-d"), datetime(2021, 5, 12).strftime("%Y%-m%-d"), datetime(2021, 6, 10).strftime("%Y%-m%-d"), datetime(2021, 7, 13).strftime("%Y%-m%-d"), datetime(2021, 8, 11).strftime("%Y%-m%-d"), datetime(2021, 9, 14).strftime("%Y%-m%-d"), datetime(2021, 10, 13).strftime("%Y%-m%-d"), datetime(2021, 11, 10).strftime("%Y%-m%-d"), datetime(2021, 12, 10).strftime("%Y%-m%-d"), datetime(2022, 1, 12).strftime("%Y%-m%-d"), datetime(2022, 2, 10).strftime("%Y%-m%-d"), datetime(2022, 3, 10).strftime("%Y%-m%-d"), datetime(2022, 4, 12).strftime("%Y%-m%-d"), datetime(2022, 5, 11).strftime("%Y%-m%-d"), datetime(2022, 6, 10).strftime("%Y%-m%-d"), datetime(2022, 7, 13).strftime("%Y%-m%-d"), datetime(2022, 8, 10).strftime("%Y%-m%-d"), datetime(2022, 9, 13).strftime("%Y%-m%-d"), datetime(2022, 10, 13).strftime("%Y%-m%-d"), datetime(2022, 11, 10).strftime("%Y%-m%-d"), datetime(2022, 12, 13).strftime("%Y%-m%-d"), ] USE_CPI_NEXTDAY = True CPI_NEXTDAY = [ datetime(2021, 1, 14).strftime("%Y%-m%-d"), datetime(2021, 2, 11).strftime("%Y%-m%-d"), datetime(2021, 3, 11).strftime("%Y%-m%-d"), datetime(2021, 4, 14).strftime("%Y%-m%-d"), datetime(2021, 5, 13).strftime("%Y%-m%-d"), datetime(2021, 6, 11).strftime("%Y%-m%-d"), datetime(2021, 7, 14).strftime("%Y%-m%-d"), datetime(2021, 8, 12).strftime("%Y%-m%-d"), datetime(2021, 9, 15).strftime("%Y%-m%-d"), datetime(2021, 10, 14).strftime("%Y%-m%-d"), datetime(2021, 11, 11).strftime("%Y%-m%-d"), datetime(2021, 12, 11).strftime("%Y%-m%-d"), datetime(2022, 1, 13).strftime("%Y%-m%-d"), datetime(2022, 2, 11).strftime("%Y%-m%-d"), datetime(2022, 3, 11).strftime("%Y%-m%-d"), datetime(2022, 4, 13).strftime("%Y%-m%-d"), datetime(2022, 5, 12).strftime("%Y%-m%-d"), datetime(2022, 6, 11).strftime("%Y%-m%-d"), datetime(2022, 7, 14).strftime("%Y%-m%-d"), datetime(2022, 8, 11).strftime("%Y%-m%-d"), datetime(2022, 9, 14).strftime("%Y%-m%-d"), datetime(2022, 10, 14).strftime("%Y%-m%-d"), datetime(2022, 11, 11).strftime("%Y%-m%-d"), datetime(2022, 12, 14).strftime("%Y%-m%-d"), ]
from AlgorithmImports import * import calendar_info class CheckCalendar(): def __init__(self, algorithm, close_trading_window, open_window, close_window): self.algorithm = algorithm # POWELL self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 1, 14), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 2, 10), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 3, 4), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 5, 3), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 6, 22), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 8, 17), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 11, 29), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 5, 17), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 9, 23), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 11, 30), self.algorithm.TimeRules.At(12,0), close_trading_window) # FED INTEREST RATE self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 1, 27), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 3, 17), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 4, 28), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 6, 16), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 7, 28), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 9, 22), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 11, 3), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 12, 15), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 1, 26), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 3, 16), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 5, 4), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 6, 15), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 7, 27), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 9, 21), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 11, 2), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 12, 4), self.algorithm.TimeRules.At(12,0), close_trading_window) # FOMC MINUTES self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 1, 6), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 2, 17), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 4, 7), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 5, 19), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 7, 7), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 8, 18), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 10, 13), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2021, 11, 24), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 1, 5), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 2, 16), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 4, 6), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 5, 25), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 7, 6), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 8, 17), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 10, 12), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.On(2022, 11, 23), self.algorithm.TimeRules.At(12,0), close_trading_window) self.algorithm.Schedule.On(self.algorithm.DateRules.Every(DayOfWeek.Friday), self.algorithm.TimeRules.At(9, 31), open_window) self.algorithm.Schedule.On(self.algorithm.DateRules.Every(DayOfWeek.Friday), self.algorithm.TimeRules.At(15, 59), close_window) self.algorithm.Schedule.On(self.algorithm.DateRules.Every(DayOfWeek.Monday), self.algorithm.TimeRules.At(9, 31), open_window) self.algorithm.Schedule.On(self.algorithm.DateRules.Every(DayOfWeek.Monday), self.algorithm.TimeRules.At(15, 59), close_window) self.algorithm.Schedule.On(self.algorithm.DateRules.Every(DayOfWeek.Wednesday), self.algorithm.TimeRules.At(9, 31), open_window) self.algorithm.Schedule.On(self.algorithm.DateRules.Every(DayOfWeek.Wednesday), self.algorithm.TimeRules.At(15, 59), close_window)
#region imports from AlgorithmImports import * from datetime import * data_dictionary = {} QUANTITY = 20 ################################################################## RE ENTRY ######################################################################## USE_RE_ENTRY = False # Pick between "SAME CONDOR" and "ANY CONDOR" # SAME CONDOR will make it so that only the previously invested Iron Condor is Re entered, # ANY CONDOR will re enter any Iron Condor RE_ENTRY_MODE = "SAME CONDOR" # Pick between "STATIC" and "ENTRY MULTIPLIER" # STATIC is a static threshold, # ENTRY MULTIPLIER multiplies the previous entry premium and sets that as the new entry premium for the re-entry RE_ENTRY_THRESHOLD_MODE = "STATIC" # ENTRY MULTIPLIER multiplies the previous entry premium and sets that as the new entry premium for the re-entry RE_ENTRY_MULTIPLIER = 1.33 # STATIC is a static threshold RE_ENTRY_STATIC_PREMIUM = 4.00 RE_ENTRY_X_TIMES = 2 ################################################################## AVG DOWN ######################################################################## USE_AVG_DOWN = False # Pick between "PERCENTAGE" or "PIVOT POINT" or "PERCENTAGE PIVOT POINT" or "FIXED" or "FIXED PIVOT POINT" AVG_DOWN_MODE = "PERCENTAGE PIVOT POINT" # True or False, # If True the most recent entry price of the condor will be used to calculate the AVG_DOWN_PERCENTAGE, otherwise the first entry of the day USE_MOST_RECENT_ENTRY = False # Fixed premium threshold at which we will average down FIXED_AVG_DOWN_PREMIUM = 2.50 # Percentage that premium needs to be higher than entry in order to average down, # 1.4 here would multiply the last entry premium by 1.4 AVG_DOWN_PERCENTAGE = 1.33 # The maximum amount of times averaging down is allowed per day AVG_DOWN_X_TIMES = 1 AVG_DOWN_QUANTITY = 10 ################################################################## SL AT ENTRY ######################################################################## USE_SL_AT_ENTRY = False # Profit Percentage that needs to be reached before allowing a stop loss at entry premium SL_AT_ENTRY_THRESHOLD = 75 # Pick between "FIRST ENTRY" or "MOST RECENT ENTRY" or "AVG ENTRY" # "FIRST ENTRY" will use the first entry to calculate the Profit Percentage, # "MOST RECENT ENTRY" will use the most recent entry to calculate the Profit Percentage, # "AVG ENTRY" will calculate the total average entry price and use that to calculate the Profit Percentage SL_AT_ENTRY_MODE = "FIRST ENTRY" ################################################################## STOP LOSS ######################################################################## # Pick between True or False USE_STOP_LOSS = False # Pick between "FIRST ENTRY" or "MOST RECENT ENTRY" or "AVG ENTRY" # "FIRST ENTRY" will use the first entry to calculate the Stop Percentage, # "MOST RECENT ENTRY" will use the most recent entry to calculate the Stop Percentage, # "AVG ENTRY" will calculate the total average entry price and use that to calculate the Stop Percentage STOP_LOSS_MODE = "FIRST ENTRY" # Multiplier applied to entry premium STOP_LOSS_MULTIPLIER = 10 # Pick between True or False USE_ABSOLUTE_STOP_LOSS = False # Premium above entry at which position will be closed ABSOLUTE_STOP_LOSS = 3 ################################################################## IRON CONDOR SETTINGS RANGE ######################################################################## # Pick between "FIXED" or "AUTOMATIC" # Fixed will use the MINIMUM and MAXIMUM DISTANCE below # Automatic will use the AUTOMATIC RANGE PERCENTAGES below RANGE_MODE = "AUTOMATIC" # Fixed Minimum Distance the Iron Condor needs to have from opening price of the day MINIMUM_DISTANCE = 1.5 # Fixed Maximum Distance the Iron Condor is allowed to have from opening price of the day # Need a maximum here since there will not always be an Iron Condor at an exact percentage, recommended for this to be 0.3% higher than, # the minimum above MAXIMUM_DISTANCE = 1.8 # Minimum Strike Difference MINIMUM_STRIKE_DIFFERENCE = 30 # Maximum Strike Difference MAXIMUM_STRIKE_DIFFERENCE = 60 # Control which range it is allowed to automatically select # Pick between 1, 1.5, 2, 2.5, 3 # If a number is included the set logic will be applied to automatically select that range if the conditions are met # Below are the conditions for each range: # 3% = VIX above 30 # 2.5% = VIX above 25 and ATR% above 2% # 2% = VIX below 25 or ATR% below 2% # 1.5% = VIX below 25 and ATR% below 2% # 1% = VIX below 20 and ATR% below 1.5% AUTOMATIC_RANGE_PERCENTAGES = [1.5, 2, 2.5, 3] # Percentage added to the minimums in the list above to create the maximum for the ranges AUTOMATIC_RANGE_MAX_ADD = 0.3 # VIX Threshold for deciding if 3% range is needed VIX_THRESHOLD_1 = 30 # VIX Threshold for deciding if 2.5% or 2% range is needed VIX_THRESHOLD_2 = 25 # VIX Threshold for deciding if 1% or 1.5% range is needed VIX_THRESHOLD_3 = 20 # ATR Threshold for deciding if 1.5% or 2% or 2.5% range is needed ATR_THRESHOLD_1 = 0.02 # ATR Threshold for deciding if 1% or 1.5%range is needed ATR_THRESHOLD_2 = 0.02 ################################################################## IRON CONDOR SETTINGS PREMIUM ######################################################################## # Pick between "FIXED" or "ADJUSTED PREMIUM" or "FIXED PER RANGE" # "FIXED" selects the same fixed minimum premium for every range, # "ADJUSTED PREMIUM" uses the premium adjuster to automatically select the minimum premium for any range # "FIXED PER RANGE" selects a different fixed minimum premium per range PREMIUM_THRESHOLD_MODE = "FIXED" # Lookback Length for the Average Premium that the Premium Adjuster Uses PREMIUM_ADJUST_LENGTH = 10 # Fixed Premium for all Ranges FIXED_PREMIUM = 0.70 # Fixed Premium if the range is 1% FIXED_PREMIUM_1 = 2.5 # Fixed Premium if the range is 1.5% FIXED_PREMIUM_1_5 = 2.50 # Fixed Premium if the range is 2% FIXED_PREMIUM_2 = 2.50 # Fixed Premium if the range is 2.5% FIXED_PREMIUM_2_5 = 2.50 # Fixed Premium if the range is 3% FIXED_PREMIUM_3 = 2.50 ################################################################## OTHER EXIT SETTINGS ######################################################################## # Pick between "FIRST ENTRY" or "MOST RECENT ENTRY" or "AVG ENTRY" # "FIRST ENTRY" will use the first entry to calculate the Profit Percentage, # "MOST RECENT ENTRY" will use the most recent entry to calculate the Profit Percentage, # "AVG ENTRY" will calculate the total average entry price and use that to calculate the Profit Percentage PROFIT_TAKING_MODE = "FIRST ENTRY" # Pick between True or False # This enables/disables the regular profit taking USE_REGULAR_PROFIT_TAKE = True # Profit percentage for regular profit taking, 50 = 50% profit REGULAR_PROFIT_PERCENTAGE = 90 # Pick between True or False # If within X Minutes after entry there is atleast X% of Profit then exit USE_TIMED_PROFIT_EXIT = True # If within X Minutes after entry there is atleast X% of Profit then exit MINUTES_AFTER_ENTRY = timedelta(minutes=60) # If within X Minutes after entry there is atleast X% of Profit then exit TIMED_PROFIT_PERCENTAGE = 50 # Pick between True or False # A simple timed exit in minutes after entry or fixed time of day, USE_TIMED_EXIT = False # Pick between "SIMPLE" or "FIXED TIME" # "SIMPLE" exits the position after X minutes regardless of time of day, profit/loss etc. # "FIXED TIME" exits the position at a fixed time of day regardless of how many minutes after entry, profit/loss etc. TIMED_EXIT_MODE = "SIMPLE" # "SIMPLE" exits the position after X minutes regardless of time of day, profit/loss etc. TIMED_EXIT_MINUTES = timedelta(minutes=50) # "FIXED TIME" exits the position at a fixed time of day regardless of how many minutes after entry, profit/loss etc. TIMED_EXIT_FIXED = time(hour=12, minute=0)
from AlgorithmImports import * from iron_condor import IronCondor import config class CreateCondors(): def __init__(self, algorithm): self.algorithm = algorithm def populate_lists(self, optionschain, symbol, symbolData, open_price, min_range, max_range): put_list = [] call_list = [] if optionschain is None: return #for i in optionschain: #if i.Key != symbolData.option_symbol: continue # optionchain = i.Value #if (optionschain.Count == 0): #return price = self.algorithm.Securities[symbol].Price price = math.floor(price) if open_price is None: open_price = self.algorithm.Securities[symbol].Open #self.algorithm.Debug(f"{self.algorithm.Time} {open_price}") List_Of_Distances = [] put_3_expiry = [x for x in optionschain if x.Right == OptionRight.Put and ((x.Expiry - self.algorithm.Time).days) == -1 and (x.Strike - price) < 1] call_3_expiry = [x for x in optionschain if x.Right == OptionRight.Call and ((x.Expiry - self.algorithm.Time).days) == -1 and (price - x.Strike) < 1] put_3_min_distance = price*1 put_3_min_distance = math.floor(put_3_min_distance) put_3_min_distances_sell = [x for x in put_3_expiry] put_3_min_distances_buy = [x for x in put_3_expiry] call_3_min_distance = price*1 call_3_min_distance = math.ceil(call_3_min_distance) call_3_min_distances_sell = [x for x in call_3_expiry] call_3_min_distances_buy = [x for x in call_3_expiry] put_3_min_distances_sorted_sell = sorted(put_3_min_distances_sell, key=lambda x: x.Strike, reverse=True) call_3_min_distances_sorted_sell = sorted(call_3_min_distances_sell, key=lambda x: x.Strike, reverse=False) put_3_min_distances_sorted_buy = sorted(put_3_min_distances_buy, key=lambda x: x.Strike, reverse=True) call_3_min_distances_sorted_buy = sorted(call_3_min_distances_buy, key=lambda x: x.Strike, reverse=False) for x in put_3_min_distances_sorted_sell: for y in put_3_min_distances_sorted_buy: strike_diff = x.Strike - y.Strike if x.Strike > y.Strike and strike_diff >= config.MINIMUM_STRIKE_DIFFERENCE and strike_diff <= config.MAXIMUM_STRIKE_DIFFERENCE: combo = (x, y) put_list.append(combo) for x in call_3_min_distances_sorted_sell: for y in call_3_min_distances_sorted_buy: strike_diff = y.Strike - x.Strike if y.Strike > x.Strike and strike_diff >= config.MINIMUM_STRIKE_DIFFERENCE and strike_diff <= config.MAXIMUM_STRIKE_DIFFERENCE: combo = (x, y) call_list.append(combo) return self.create_combinations(min_range, max_range, put_list, call_list, open_price) def create_combinations(self, min_range, max_range, put_list, call_list, open_price): keys = [] condors = {} appended_1 = None appended_1_5 = None appended_2 = None appended_2_5 = None appended_3 = None for ps, pb in put_list: for cs, cb in call_list: p_diff = ps.Strike - pb.Strike c_diff = cb.Strike - cs.Strike if cs.Strike > ps.Strike and p_diff == c_diff and open_price is not None: open_call_range = ((cs.Strike - open_price) / open_price) open_put_range = abs((ps.Strike - open_price) / open_price) Strikes = f"{pb.Strike} {ps.Strike} {cs.Strike} {cb.Strike} {open_call_range} {open_put_range} {p_diff}" if Strikes not in condors: condors[Strikes] = IronCondor(self.algorithm, pb, ps, cb, cs, open_call_range, open_put_range) max_max = (max_range + 0.003) if open_put_range >= min_range and open_call_range >= min_range and open_put_range <= max_max and open_call_range <= max_max: diff = abs(open_call_range - open_put_range) percent = (open_call_range + open_put_range) / 2 tup = (Strikes, percent, diff, p_diff) keys.append(tup) if appended_2_5 is None and open_call_range >= 0.024 and open_call_range <= 0.027 and open_put_range >= 0.024 and open_put_range <= 0.027: condor = condors[Strikes] appended_2_5 = condor if appended_2 is None and open_call_range >= 0.02 and open_call_range <= 0.022 and open_put_range >= 0.02 and open_put_range <= 0.022: condor = condors[Strikes] appended_2 = condor if appended_3 is None and open_call_range >= 0.03 and open_call_range <= 0.032 and open_put_range >= 0.03 and open_put_range <= 0.032: condor = condors[Strikes] appended_3 = condor if appended_1_5 is None and open_call_range >= 0.015 and open_call_range <= 0.017 and open_put_range >= 0.015 and open_put_range <= 0.017: condor = condors[Strikes] appended_1_5 = condor if appended_1 is None and open_call_range >= 0.01 and open_call_range <= 0.013 and open_put_range >= 0.01 and open_put_range <= 0.013: condor = condors[Strikes] appended_1 = condor return condors, keys, appended_1, appended_1_5, appended_2, appended_2_5, appended_3
from AlgorithmImports import * class DataManager(): def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.callables = config.data_dictionary self.consolidators = {} self.indicators = {} for key, value in self.callables.items(): for tup in value: # tup is one of the tuples in the list # you can unpack the tuple into variables here function, indicator_name, indicator, period, consolidator_name, resolution, delta = tup if consolidator_name not in self.consolidators: function_receive = self.create_receive_bar_function() self.consolidators[consolidator_name] = TradeBarConsolidator(delta) self.algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.consolidators[consolidator_name]) self.consolidators[consolidator_name].DataConsolidated += function_receive
from AlgorithmImports import * import config class EntryManager(): def __init__(self, algorithm, symbol, re_entry_manager, avg_down_manager): self.algorithm = algorithm self.symbol = symbol self.re_entry_manager = re_entry_manager self.avg_down_manager = avg_down_manager def check_re_entry(self, condors, keys, min_range, max_range, premium_threshold): price = self.algorithm.Securities[self.symbol].Price option_invested = [x.Key for x in self.algorithm.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.IndexOption and x.Key.Underlying == self.symbol] if len(option_invested) > 0: invested = True else: invested = False if self.re_entry_manager.check_permission(invested): for key in keys: condor = condors[key[0]] if condor.Calculate_Premium() >= premium_threshold and condor.check_range(min_range, max_range): if self.re_entry_manager.re_entry_mode == "SAME CONDOR" and key != self.re_entry_manager.allowed_condor: continue else: self.algorithm.MarketOrder(condor.Put_Buy.Symbol, config.QUANTITY, tag =f"{condor.open_put_range} Strike {condor.Put_Buy.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Put_Sell.Symbol, -config.QUANTITY, tag =f"{condor.open_put_range} Strike {condor.Put_Sell.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Call_Buy.Symbol, config.QUANTITY, tag =f"{condor.open_call_range} Strike {condor.Call_Buy.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Call_Sell.Symbol, -config.QUANTITY, tag =f"{condor.open_call_range} Strike {condor.Call_Sell.Strike} pm {condor.Premium} Price {price}") self.re_entry_manager.allowed_condor = key self.re_entry_manager.previous_premium = condor.Premium self.re_entry_manager.entered_today = True self.re_entry_manager.entry_count_today += 1 condor.entry_premiums.clear() condor.entry_premium = condor.Premium condor.calculate_avg_entry() condor.entry_time = self.algorithm.Time if condor.first_entry is None: condor.first_entry = condor.Premium return condor def check_avg_down(self, condors, keys, min_range, max_range, premium_threshold): price = self.algorithm.Securities[self.symbol].Price option_invested = [x.Key for x in self.algorithm.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.IndexOption and x.Key.Underlying == self.symbol] if len(option_invested) > 0: invested = True else: invested = False if invested: for key in keys: if key != self.avg_down_manager.entered_key: continue condor = condors[key[0]] if self.avg_down_manager.check_avg_down(): self.algorithm.Debug(f"{self.algorithm.Time} AVERAGED DOWN") self.algorithm.MarketOrder(condor.Put_Buy.Symbol, config.AVG_DOWN_QUANTITY, tag =f"{condor.open_put_range} Strike {condor.Put_Buy.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Put_Sell.Symbol, -config.AVG_DOWN_QUANTITY, tag =f"{condor.open_put_range} Strike {condor.Put_Sell.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Call_Buy.Symbol, config.AVG_DOWN_QUANTITY, tag =f"{condor.open_call_range} Strike {condor.Call_Buy.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Call_Sell.Symbol, -config.AVG_DOWN_QUANTITY, tag =f"{condor.open_call_range} Strike {condor.Call_Sell.Strike} pm {condor.Premium} Price {price}") self.re_entry_manager.allowed_condor = key self.re_entry_manager.previous_premium = condor.Premium self.re_entry_manager.entered_today = True self.avg_down_manager.entered_condor = condor self.avg_down_manager.entered_key = key self.avg_down_manager.avg_down_counter += 1 condor.entry_premium = condor.Premium condor.calculate_avg_entry() condor.entry_time = self.algorithm.Time if self.avg_down_manager.first_entry is None: self.avg_down_manager.first_entry = condor.Premium if condor.first_entry is None: condor.first_entry = condor.Premium return condor def check_regular(self, condors, keys, min_range, max_range, premium_threshold): price = self.algorithm.Securities[self.symbol].Price option_invested = [x.Key for x in self.algorithm.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.IndexOption and x.Key.Underlying == self.symbol] if len(option_invested) > 0: invested = True else: invested = False if not invested and not self.re_entry_manager.entered_today: for key in keys: condor = condors[key[0]] #self.algorithm.Debug(f"{condor.Calculate_Premium()} {premium_threshold} {condor.check_range(min_range, max_range)}") if condor.Calculate_Premium() >= premium_threshold and condor.check_range(min_range, max_range): self.algorithm.MarketOrder(condor.Put_Buy.Symbol, config.QUANTITY, tag =f"{condor.open_put_range} Strike {condor.Put_Buy.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Put_Sell.Symbol, -config.QUANTITY, tag =f"{condor.open_put_range} Strike {condor.Put_Sell.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Call_Buy.Symbol, config.QUANTITY, tag =f"{condor.open_call_range} Strike {condor.Call_Buy.Strike} pm {condor.Premium} Price {price}") self.algorithm.MarketOrder(condor.Call_Sell.Symbol, -config.QUANTITY, tag =f"{condor.open_call_range} Strike {condor.Call_Sell.Strike} pm {condor.Premium} Price {price}") self.re_entry_manager.allowed_condor = key self.re_entry_manager.previous_premium = condor.Premium self.re_entry_manager.entered_today = True self.avg_down_manager.entered_condor = condor self.avg_down_manager.entered_key = key condor.entry_premium = condor.Premium condor.calculate_avg_entry() condor.entry_time = self.algorithm.Time if self.avg_down_manager.first_entry is None: self.avg_down_manager.first_entry = condor.Premium if condor.first_entry is None: condor.first_entry = condor.Premium return condor
from AlgorithmImports import * import config class ExitManager(): def __init__(self, algorithm, symbol, close_trading_window): self.algorithm = algorithm self.symbol = symbol self.use_stop_loss = config.USE_STOP_LOSS self.stop_loss_mode = config.STOP_LOSS_MODE self.stop_loss_multiplier = config.STOP_LOSS_MULTIPLIER self.use_absolute_stop_loss = config.USE_ABSOLUTE_STOP_LOSS self.absolute_stop_loss = config.ABSOLUTE_STOP_LOSS self.use_regular_profit_take = config.USE_REGULAR_PROFIT_TAKE self.profit_taking_mode = config.PROFIT_TAKING_MODE self.regular_profit_percentage = 1 - (config.REGULAR_PROFIT_PERCENTAGE/100) self.use_timed_profit_exit = config.USE_TIMED_PROFIT_EXIT self.minutes_after_entry = config.MINUTES_AFTER_ENTRY self.timed_profit_percentage = 1 - (config.TIMED_PROFIT_PERCENTAGE/100) self.use_timed_exit = config.USE_TIMED_EXIT self.timed_exit_mode = config.TIMED_EXIT_MODE self.timed_Exit_minutes = config.TIMED_EXIT_MINUTES self.timed_exit_fixed = config.TIMED_EXIT_FIXED #self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.BeforeMarketClose(self.symbol, 1), close_trading_window) def check_stop_loss(self, condor): if self.stop_loss_mode == "FIRST_ENTRY": if condor.Calculate_Premium >= condor.first_entry * self.stop_loss_multiplier: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.stop_loss_mode == "MOST RECENT ENTRY": if condor.Calculate_Premium >= condor.entry_premium * self.stop_loss_multiplier: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.stop_loss_mode == "AVG ENTRY": if condor.Calculate_Premium >= condor.avg_entry * self.stop_loss_multiplier: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) else: raise Exception(f"Please input a correct STOP LOSS MODE in the config file. {config.STOP_LOSS_MODE} is incorrect") def check_absolute_stop_loss(self, condor): if self.stop_loss_mode == "FIRST_ENTRY": if condor.Calculate_Premium() >= condor.first_entry + self.absolute_stop_loss: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.stop_loss_mode == "MOST RECENT ENTRY": if condor.Calculate_Premium() >= condor.entry_premium + self.absolute_stop_loss: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.stop_loss_mode == "AVG ENTRY": if condor.Calculate_Premium() >= condor.avg_entry + self.absolute_stop_loss: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) def check_regular_profit_take(self, condor): if self.profit_taking_mode == "FIRST_ENTRY": if condor.Calculate_Premium() <= condor.first_entry * self.regular_profit_percentage: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.profit_taking_mode == "MOST RECENT ENTRY": if condor.Calculate_Premium() <= condor.entry_premium * self.regular_profit_percentage: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.profit_taking_mode == "AVG ENTRY": if condor.Calculate_Premium() <= condor.avg_entry * self.regular_profit_percentage: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) def check_timed_profit_exit(self, condor): if self.algorithm.Time <= condor.entry_time + self.minutes_after_entry: if self.profit_taking_mode == "FIRST_ENTRY": if condor.Calculate_Premium() <= condor.first_entry * self.timed_profit_percentage: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.profit_taking_mode == "MOST RECENT ENTRY": if condor.Calculate_Premium() <= condor.entry_premium * self.timed_profit_percentage: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.profit_taking_mode == "AVG ENTRY": if condor.Calculate_Premium() <= condor.avg_entry * self.timed_profit_percentage: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) def check_timed_exit(self, condor): if self.timed_exit_mode == "SIMPLE": if condor.entry_time + self.timed_Exit_minutes >= self.algorithm.Time: self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol) elif self.timed_exit_mode == "FIXED TIME": if self.timed_exit_fixed.strftime("%H%M") >= self.algorithm.Time.strftime("%H%M"): self.algorithm.Liquidate(condor.Call_Sell.Symbol) self.algorithm.Liquidate(condor.Call_Buy.Symbol) self.algorithm.Liquidate(condor.Put_Sell.Symbol) self.algorithm.Liquidate(condor.Put_Buy.Symbol)
#region imports from AlgorithmImports import * from collections import deque #endregion import config import statistics as stats class IronCondor(): def __init__(self, algorithm, put_buy, put_sell, call_buy, call_sell, open_call_range, open_put_range): self.algorithm = algorithm self.Put_Buy = put_buy self.Put_Sell = put_sell self.Call_Buy = call_buy self.Call_Sell = call_sell self.Sent_Already = False self.Premium = None self.entry_premium = None self.Entry_Fees = None self.first_entry = None self.entry_premiums = [] self.avg_entry = None self.Lowest_Premium = None self.Scanned_Already = False self.entry_time = None self.Reached_Threshold = False self.Profit = None self.Stopped_Out = False self.Profit_Taken = False self.Current_Profit = None self.Margin_Required = None self.open_call_range = open_call_range self.open_put_range = open_put_range self.Sent_Open_Range = False self.Highest_Premium = -1000000 self.Weight = 0 self.Entered_Increments = [] #self.Avg_Down_Type = config.AVG_DOWN_TYPE #self.Underlying_Increment = config.UNDERLYING_PERCENT_MOVE_INCREMENT/100 self.Pivot_Queue = deque(maxlen=3) def check_range(self, min_range, max_range): if self.open_call_range >= min_range and self.open_put_range >= min_range and self.open_call_range <= max_range and self.open_put_range <= max_range: return True else: return False def calculate_avg_entry(self): self.entry_premiums.append(self.entry_premium) self.avg_entry = stats.mean(self.entry_premiums) def Calculate_Premium(self): cs_premium = self.algorithm.Securities[self.Call_Sell.Symbol].BidPrice cb_premium = self.algorithm.Securities[self.Call_Buy.Symbol].AskPrice ps_premium = self.algorithm.Securities[self.Put_Sell.Symbol].BidPrice pb_premium = self.algorithm.Securities[self.Put_Sell.Symbol].AskPrice call_premium = cs_premium - cb_premium put_premium = ps_premium - pb_premium list_of_ba = [-pb_premium, ps_premium, -cb_premium, cs_premium] self.Premium = sum(list_of_ba) return self.Premium def Append_Pivot(self): if self.Entry_Premium is not None: self.Calculate_Premium(self.algorithm.Securities[self.Put_Buy.Symbol].AskPrice, self.algorithm.Securities[self.Put_Sell.Symbol].BidPrice, self.algorithm.Securities[self.Call_Buy.Symbol].AskPrice, self.algorithm.Securities[self.Call_Sell.Symbol].BidPrice) self.Pivot_Queue.appendleft(self.Premium) def Calculate_Avg_Down(self): if self.Entry_Premium is not None: if config.USE_PIVOT and not config.USE_PERCENTAGE: if len(self.Pivot_Queue) == 3 and self.Pivot_Queue[0] < self.Pivot_Queue[1] > self.Pivot_Queue[2]: self.algorithm.Debug(f"{self.algorithm.Time} PIVOT POINT AVG DOWN") return True else: return False elif config.USE_PERCENTAGE and not config.USE_PIVOT: if self.Premium > (self.Entry_Premium * self.Premium_Increase): self.algorithm.Debug(f"{self.algorithm.Time} PERCENTAGE AVG DOWN") return True else: return False elif config.USE_PERCENTAGE and config.USE_PIVOT: if len(self.Pivot_Queue) == 3 and self.Pivot_Queue[0] < self.Pivot_Queue[1] > self.Pivot_Queue[2] and self.Premium > (self.Entry_Premium * self.Premium_Increase): self.algorithm.Debug(f"{self.algorithm.Time} BOTH AVG DOWN") return True else: return False else: return False else: return False #def Calculate_Underlying_Re_Entry(self): #if
# region imports from AlgorithmImports import * from symboldata import SymbolData from create_condors import CreateCondors from select_range import SelectRange from adjust_premium import PremiumThresholdAdjuster from select_premium import PremiumSelecter from re_entry import ReEntry from entry import EntryManager from avg_down import AvgDown from exits import ExitManager from check_calendar import CheckCalendar class AlertBlackBull(QCAlgorithm): def Initialize(self): self.SetStartDate(2022, 1, 1) # Set Start Date self.SetEndDate(2023, 1, 18) self.SetCash(1000000) # Set Strategy Cash self.symbol = self.AddIndex("SPX", Resolution.Minute).Symbol self.condor_creator = CreateCondors(self) self.range_selector = SelectRange(self, self.symbol) self.premium_adjuster = PremiumThresholdAdjuster(self) self.premium_selector = PremiumSelecter(self) self.re_entry_manager = ReEntry(self, self.symbol) self.avg_down_manager = AvgDown(self, self.symbol) self.entry_manager = EntryManager(self, self.symbol, self.re_entry_manager, self.avg_down_manager) self.exit_manager = ExitManager(self, self.symbol, self.close_if_at_loss) self.calendar_checker = CheckCalendar(self, self.close_trading_window, self.open_window, self.close_window) self.symbol_dictionary = {} self.symbol_dictionary[self.symbol] = SymbolData(self, self.symbol) self.created_combinations_today = False self.trading_window = False self.open_price = None self.today_condors = None self.today_keys = None self.todays_premium = None self.todays_min_range = None self.todays_max_range = None self.invested_condor = None def open_window(self): #self.Debug(self.Time) self.open_price = self.Securities[self.symbol].Open self.trading_window = True def close_window(self): self.close_if_at_loss() self.created_combinations_today = False self.trading_window = False self.today_condors = None self.today_keys = None self.todays_premium = None self.todays_min_range = None self.todays_max_range = None self.invested_condor = None self.re_entry_manager.reset() self.avg_down_manager.reset() def close_trading_window(self): self.Liquidate() self.created_combinations_today = False self.trading_window = False self.today_condors = None self.today_keys = None self.todays_premium = None self.todays_min_range = None self.todays_max_range = None self.invested_condor = None self.re_entry_manager.reset() self.avg_down_manager.reset() def close_if_at_loss(self): if self.invested_condor is not None: #self.Debug(f"{self.Securities[self.symbol].High+0.2} {self.Securities[self.symbol].Low-0.2}") if self.Securities[self.symbol].High+0.2 >= self.invested_condor.Call_Sell.Strike: #self.Debug(f"{self.Time} {self.invested_condor}") self.created_combinations_today = False self.trading_window = False self.today_condors = None self.today_keys = None self.todays_premium = None self.todays_min_range = None self.todays_max_range = None self.invested_condor = None self.re_entry_manager.reset() self.avg_down_manager.reset() self.Liquidate(tag="At loss") elif self.Securities[self.symbol].Low-0.2 <= self.invested_condor.Put_Sell.Strike: #self.Debug(f"{self.Time} {self.invested_condor}") self.created_combinations_today = False self.trading_window = False self.today_condors = None self.today_keys = None self.todays_premium = None self.todays_min_range = None self.todays_max_range = None self.invested_condor = None self.re_entry_manager.reset() self.avg_down_manager.reset() self.Liquidate(tag="At loss") def OnData(self, slice): if self.trading_window: for symbol, symbolData in self.symbol_dictionary.items(): chain = slice.OptionChains.GetValue(symbolData.option_symbol) if not self.created_combinations_today: min_range, max_range = self.range_selector.set_range_today() self.todays_min_range = min_range self.todays_max_range = max_range if self.open_price is None: self.open_price = self.Securities[self.symbol].Open if chain is None: return condors, keys, appended_1, appended_1_5, appended_2, appended_2_5, appended_3 = self.condor_creator.populate_lists(chain, self.symbol, symbolData, self.open_price, min_range, max_range) self.today_condors = condors keys.sort(key=lambda tup: (tup[1], tup[2], -tup[3]), reverse=False) self.today_keys = keys self.premium_adjuster.receive_condors(appended_1, appended_1_5, appended_2, appended_2_5, appended_3) adjustable_premium_today = self.premium_adjuster.return_premium_today(min_range) self.todays_premium = self.premium_selector.select_premium(min_range, adjustable_premium_today) self.created_combinations_today = True #self.Debug(len(keys)) if self.invested_condor is not None: if self.exit_manager.use_stop_loss: self.exit_manager.check_stop_loss(self.invested_condor) if self.exit_manager.use_absolute_stop_loss: self.exit_manager.check_absolute_stop_loss(self.invested_condor) if self.exit_manager.use_regular_profit_take: self.exit_manager.check_regular_profit_take(self.invested_condor) if self.exit_manager.use_timed_exit: self.exit_manager.check_timed_exit(self.invested_condor) if self.exit_manager.use_timed_profit_exit: self.exit_manager.check_timed_profit_exit(self.invested_condor) if self.avg_down_manager.use_avg_down: self.avg_down_manager.append_pivot() if self.invested_condor is None: self.invested_condor = self.entry_manager.check_regular(self.today_condors, self.today_keys, self.todays_min_range, self.todays_max_range, self.todays_premium) if self.re_entry_manager.use_re_entry: self.invested_condor = self.entry_manager.check_re_entry(self.today_condors, self.today_keys, self.todays_min_range, self.todays_max_range, self.todays_premium) if self.avg_down_manager.use_avg_down: self.invested_condor = self.entry_manager.check_avg_down(self.today_condors, self.today_keys, self.todays_min_range, self.todays_max_range, self.todays_premium)
from AlgorithmImports import * from collections import deque import statistics as stats import config class ReEntry(): def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.use_re_entry = config.USE_RE_ENTRY self.re_entry_mode = config.RE_ENTRY_MODE self.re_entry_threshold_mode = config.RE_ENTRY_THRESHOLD_MODE self.re_entry_multiplier = config.RE_ENTRY_MULTIPLIER self.re_entry_static = config.RE_ENTRY_STATIC_PREMIUM self.re_entry_times_x = config.RE_ENTRY_X_TIMES self.entered_today = False self.entry_count_today = 0 self.previous_premium = None self.allowed_condor = "ANY CONDOR" def check_permission(self, invested): if not self.use_re_entry and self.entered_today: return False elif self.use_re_entry and not invested and self.entered_today and self.entry_count_today < self.re_entry_times_x: return True else: return False def get_new_threshold(self): if self.re_entry_threshold_mode == "STATIC": return self.re_entry_static elif self.re_entry_threshold_mode == "ENTRY MULTIPLIER": return self.previous_premium * self.re_entry_multiplier def reset(self): self.use_re_entry = config.USE_RE_ENTRY self.re_entry_mode = config.RE_ENTRY_MODE self.re_entry_threshold_mode = config.RE_ENTRY_THRESHOLD_MODE self.re_entry_multiplier = config.RE_ENTRY_MULTIPLIER self.re_entry_static = config.RE_ENTRY_STATIC_PREMIUM self.re_entry_times_x = config.RE_ENTRY_X_TIMES self.entered_today = False self.entry_count_today = 0 self.previous_premium = None self.allowed_condor = "ANY CONDOR"
from AlgorithmImports import * from collections import deque import statistics as stats import config class PremiumSelecter(): def __init__(self, algorithm): self.algorithm = algorithm self.premium_threshold_mode = config.PREMIUM_THRESHOLD_MODE self.fixed_premium = config.FIXED_PREMIUM self.fixed_premium_1 = config.FIXED_PREMIUM_1 self.fixed_premium_1_5 = config.FIXED_PREMIUM_1_5 self.fixed_premium_2 = config.FIXED_PREMIUM_2 self.fixed_premium_2_5 = config.FIXED_PREMIUM_2_5 self.fixed_premium_3 = config.FIXED_PREMIUM_3 def select_premium(self, range_today, adjustable_premium_today): if self.premium_threshold_mode == "FIXED": self.algorithm.Plot("Premium Used", "Premium", self.fixed_premium) return self.fixed_premium elif self.premium_threshold_mode == "FIXED PER RANGE": if range_today == 0.01: self.algorithm.Plot("Premium Used", "Premium", self.fixed_premium_1) premium_today = self.fixed_premium_1 elif range_today == 0.015: self.algorithm.Plot("Premium Used", "Premium", self.fixed_premium_1_5) premium_today = self.fixed_premium_1_5 elif range_today == 0.02: self.algorithm.Plot("Premium Used", "Premium", self.fixed_premium_2_5) premium_today = self.fixed_premium_2_5 elif range_today == 0.025: self.algorithm.Plot("Premium Used", "Premium", self.fixed_premium_2_5) premium_today = self.fixed_premium_2_5 elif range_today == 0.03: self.algorithm.Plot("Premium Used", "Premium", self.fixed_premium_3) premium_today = self.fixed_premium_3 return premium_today elif self.premium_threshold_mode == "ADJUSTED PREMIUM": self.algorithm.Plot("Premium Used", "Premium", adjustable_premium_today) return adjustable_premium_today else: raise Exception(f"Premium Threshold Mode '{config.PREMIUM_THRESHOLD_MODE}' is incorrect, please pick between 'FIXED' or 'FIXED PER RANGE' or 'ADJUSTED PREMIUM'")
from AlgorithmImports import * import config class SelectRange(): def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.range_mode = config.RANGE_MODE self.VIX = self.algorithm.AddIndex("VIX", Resolution.Minute).Symbol self.range_max_today = None self.range_min_today = None self.automatic_range_percentages = config.AUTOMATIC_RANGE_PERCENTAGES self.automatic_range_max_add = config.AUTOMATIC_RANGE_MAX_ADD/100 self.vix_threshold_1 = config.VIX_THRESHOLD_1 self.vix_threshold_2 = config.VIX_THRESHOLD_2 self.vix_threshold_3 = config.VIX_THRESHOLD_3 self.atr_threshold_1 = config.ATR_THRESHOLD_1 self.atr_threshold_2 = config.ATR_THRESHOLD_2 self.atr_21_indie = NormalizedAverageTrueRange(21) self.atr_21 = None self.vix = None self.use_1 = False self.use_1_5 = False self.use_2 = False self.use_2_5 = False self.use_3 = False self.bar_consolidator = TradeBarConsolidator(timedelta(days=1)) self.algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.bar_consolidator) self.bar_consolidator.DataConsolidated += self.temporary_receive_bar history = self.algorithm.History[TradeBar](self.symbol, 100, Resolution.Daily) for bar in history: self.bar_consolidator.Update(bar) self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.AfterMarketOpen(self.symbol, 1), self.temporary_get_vix) if self.range_mode == "FIXED": self.range_max_today = config.MAXIMUM_DISTANCE/100 self.range_min_today = config.MINIMUM_DISTANCE/100 elif self.range_mode == "AUTOMATIC": config.data_dictionary["select_range_callable"] = [(self.select_range_callable, "atr_21", NormalizedAverageTrueRange(21), 21, "1 day", Resolution.Daily, timedelta(days=1))] if 1 in self.automatic_range_percentages: self.use_1 = True if 1.5 in self.automatic_range_percentages: self.use_1_5 = True if 2 in self.automatic_range_percentages: self.use_2 = True if 2.5 in self.automatic_range_percentages: self.use_2_5 = True if 3 in self.automatic_range_percentages: self.use_3 = True else: raise Exception(f"Selected RANGE MODE {self.range_mode} is incorrect, please check the input and either choose 'AUTOMATIC' or 'FIXED'") def temporary_get_vix(self): self.vix = self.algorithm.Securities[self.VIX].Open def temporary_receive_bar(self, sender, bar): self.atr_21_indie.Update(bar) if self.atr_21_indie.IsReady: self.atr_21 = self.atr_21_indie.Current.Value/100 def select_range_callable(self, atr_21, vix): self.atr_21 = atr_21/100 self.vix = vix def set_range_today(self): #self.algorithm.Debug(f"{self.vix} {self.atr_21}") if self.range_mode == "AUTOMATIC": if self.use_1_5 and self.atr_21 <= self.atr_threshold_1 and self.vix <= self.vix_threshold_2: self.range_max_today = 0.015 + self.automatic_range_max_add self.range_min_today = 0.015 elif self.use_2 and self.atr_21 <= self.atr_threshold_1: self.range_max_today = 0.02 + self.automatic_range_max_add self.range_min_today = 0.02 elif self.use_2 and self.vix <= self.vix_threshold_2: self.range_max_today = 0.02 + self.automatic_range_max_add self.range_min_today = 0.02 elif self.use_2_5: self.range_max_today = 0.025 + self.automatic_range_max_add self.range_min_today = 0.025 if self.use_3 and self.vix >= self.vix_threshold_1: self.range_max_today = 0.03 + self.automatic_range_max_add self.range_min_today = 0.03 if self.use_1 and self.atr_21 < self.atr_threshold_2 and self.vix < self.vix_threshold_3: self.range_max_today = 0.01 + self.automatic_range_max_add self.range_min_today = 0.01 elif self.range_mode == "FIXED": pass else: raise Exception(f"Selected RANGE MODE {self.range_mode} is incorrect, please check the input and either choose 'AUTOMATIC' or 'FIXED'") self.algorithm.Plot("Range Used", "Range", self.range_min_today) return self.range_min_today , self.range_max_today
from AlgorithmImports import * from QuantConnect.Securities.Option import OptionPriceModels class SymbolData(): def __init__(self, algorithm, symbol): self.algorithm = algorithm self.symbol = symbol self.option = self.algorithm.AddIndexOption(self.symbol, "SPXW") self.option.SetLeverage(1.0) self.option_symbol = self.option.Symbol #self.option.PriceModel = OptionPriceModels.CrankNicolsonFD() self.option.SetFilter(self.UniverseFunc) def UniverseFunc(self, universe): Price = self.algorithm.Securities[self.symbol].Price ATM = self.algorithm.Securities[self.symbol].Price * 0.06 return universe.IncludeWeeklys().Strikes(-ATM, ATM).Expiration(TimeSpan.FromDays(0),TimeSpan.FromDays(1))