Overall Statistics
Total Trades
184
Average Win
0.01%
Average Loss
0.00%
Compounding Annual Return
0.134%
Drawdown
0.100%
Expectancy
0.503
Net Profit
0.134%
Sharpe Ratio
3.851
Probabilistic Sharpe Ratio
100.000%
Loss Rate
64%
Win Rate
36%
Profit-Loss Ratio
3.19
Alpha
0.001
Beta
-0.001
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-1.819
Tracking Error
0.108
Treynor Ratio
-1.789
Total Fees
$440.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
SPY XU0Z3NBDVU5I|SPY R735QTJ8XC9X
from AlgorithmImports import *
from collections import deque
import statistics as stats



class BarChange():



    def __init__(self, algorithm, symbol):
        self.algorithm = algorithm
        self.symbol = symbol

        self.Intraday_Bar_Consolidator = TradeBarConsolidator(timedelta(minutes=5))
        self.algorithm.SubscriptionManager.AddConsolidator(self.symbol, self.Intraday_Bar_Consolidator)
        self.Intraday_Bar_Consolidator.DataConsolidated += self.Calculate_Bar_Change
        self.len = 42
        self.List_Bar_Changes_OC = []
        self.List_Bar_Changes_HL = []

        self.Current_Cumulative_OC = None
        self.Current_Cumulative_HL = None

        self.Daily_Sums_OC = []
        self.Daily_Sums_HL = []

        self.Daily_Sum_Mean_OC = None
        self.Daily_Sum_Mean_HL = None

        self.Relative_OC = {"10":deque(maxlen=self.len), "11":deque(maxlen=self.len), "12":deque(maxlen=self.len), "13":deque(maxlen=self.len), "14":deque(maxlen=self.len), "15":deque(maxlen=self.len)}
        self.Relative_HL = {"10":deque(maxlen=self.len), "11":deque(maxlen=self.len), "12":deque(maxlen=self.len), "13":deque(maxlen=self.len), "14":deque(maxlen=self.len), "15":deque(maxlen=self.len)}



        self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.At(10,0), self.Append_10)
        self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.At(11,0), self.Append_11)
        self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.At(12,0), self.Append_12)
        self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.At(13,0), self.Append_13)
        self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.At(14,0), self.Append_14)
        self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.At(15,0), self.Append_15)


        self.algorithm.Schedule.On(self.algorithm.DateRules.EveryDay(), self.algorithm.TimeRules.At(23,0), self.Reset_Lists)
    

    def Append_10(self):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)
        self.Relative_OC["10"].appendleft(sum_oc)
        self.Relative_HL["10"].appendleft(sum_hl)
    

    def Append_11(self):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)
        self.Relative_OC["11"].appendleft(sum_oc)
        self.Relative_HL["11"].appendleft(sum_hl)

    
    def Append_12(self):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)
        self.Relative_OC["12"].appendleft(sum_oc)
        self.Relative_HL["12"].appendleft(sum_hl)

    
    def Append_13(self):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)
        self.Relative_OC["13"].appendleft(sum_oc)
        self.Relative_HL["13"].appendleft(sum_hl)


    def Append_14(self):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)
        self.Relative_OC["14"].appendleft(sum_oc)
        self.Relative_HL["14"].appendleft(sum_hl)


    def Append_15(self):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)
        self.Relative_OC["15"].appendleft(sum_oc)
        self.Relative_HL["15"].appendleft(sum_hl)





    def Reset_Lists(self):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)
        self.Daily_Sums_OC.append(sum_oc)
        self.Daily_Sums_HL.append(sum_hl)
        self.Daily_Sum_Mean_OC = stats.mean(self.Daily_Sums_OC)
        self.Daily_Sum_Mean_HL = stats.mean(self.Daily_Sums_HL)
        self.List_Bar_Changes_OC.clear()
        self.List_Bar_Changes_HL.clear()


    def Get_Relative_Change(self, list_sums_oc, list_sums_hl):
        sum_oc = sum(self.List_Bar_Changes_OC)
        sum_hl = sum(self.List_Bar_Changes_HL)

        relative_oc = stats.mean(list_sums_oc)
        relative_hl = stats.mean(list_sums_hl)

        ratio_oc = sum_oc / relative_oc
        ratio_hl = sum_hl / relative_hl


        return round(sum_oc, 3), round(relative_oc, 3), round(ratio_oc, 3), round(sum_hl, 3), round(relative_hl, 3), round(ratio_hl, 3)


    def Calculate_Bar_Change(self, sender, bar):
        change_OC = abs((bar.Close - bar.Open) / bar.Open)
        change_HL = abs((bar.High - bar.Low) / bar.Close)

        self.List_Bar_Changes_OC.append(change_OC)
        self.List_Bar_Changes_HL.append(change_HL)

        if len(self.List_Bar_Changes_OC) >= 1:
            self.Current_Cumulative_OC = sum(self.List_Bar_Changes_OC)
        if len(self.List_Bar_Changes_HL) >= 1:
            self.Current_Cumulative_HL = sum(self.List_Bar_Changes_HL)
#region imports
from AlgorithmImports import *
#endregion
import time





USE_FOMC_MEETINGS = True
FOMC_MEETINGS = [
                Time(2022, 1, 25).strftime("%Y%-m%-d"),
                Time(2022, 1, 26).strftime("%Y%-m%-d"),
                Time(2022, 3, 15).strftime("%Y%-m%-d"),
                Time(2022, 3, 16).strftime("%Y%-m%-d"),
                Time(2022, 5, 3).strftime("%Y%-m%-d"),
                Time(2022, 5, 4).strftime("%Y%-m%-d"),
                Time(2022, 6, 14).strftime("%Y%-m%-d"),
                time(2022, 6, 15).strftime("%Y%-m%-d"),
                time(2022, 7, 26).strftime("%Y%-m%-d"),
                time(2022, 7, 27).strftime("%Y%-m%-d"),
                time(2022, 9, 20).strftime("%Y%-m%-d"),
                time(2022, 9 ,21).strftime("%Y%-m%-d"),
                time(2022, 11, 1).strftime("%Y%-m%-d"),
                time(2022, 11, 2).strftime("%Y%-m%-d"),
                time(2022, 12, 13).strftime("%Y%-m%-d"),
                time(2022, 12, 14).strftime("%Y%-m%-d"),
                ]





USE_FOMC_MINUTES = True
FOMC_MINUTES = [
                time(2022, 2 ,16).strftime("%Y%-m%-d"),
                time(2022, 4, 6).strftime("%Y%-m%-d"),
                time(2022, 5, 25).strftime("%Y%-m%-d"),
                time(2022, 7, 6).strftime("%Y%-m%-d"),
                time(2022, 8, 17).strftime("%Y%-m%-d"),
                time(2022, 10, 12).strftime("%Y%-m%-d"),
                ]
                



USE_CPI = True
CPI =          [
                time(2022, 1, 12).strftime("%Y%-m%-d"),
                time(2022, 2, 10).strftime("%Y%-m%-d"),
                time(2022, 3, 10).strftime("%Y%-m%-d"),
                time(2022, 4, 12).strftime("%Y%-m%-d"),
                time(2022, 5, 11).strftime("%Y%-m%-d"),
                time(2022, 6, 10).strftime("%Y%-m%-d"),
                time(2022, 7, 13).strftime("%Y%-m%-d"),
                time(2022, 8, 10).strftime("%Y%-m%-d"),
                time(2022, 9, 13).strftime("%Y%-m%-d"),
                time(2022, 10, 13).strftime("%Y%-m%-d"),
                time(2022, 11, 13).strftime("%Y%-m%-d"),
                time(2022, 12, 13).strftime("%Y%-m%-d"),
                ]
#region imports
from AlgorithmImports import *
#endregion
from datetime 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 = True
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 = True
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"),

                ]

USE_PRINT_OUT = False
PRINT_OUT =     [
                datetime(2022, 9, 2).strftime("%Y%-m%-d")
                ]






USE_LOWER_THRESHOLD = False

MINIMUM_GAP = 1
MAXIMUM_GAP = 5

LIST_OF_PERCENTAGES = [0.01, 0.02, 0.03]
LIST_OF_GAPS = [4,5,6]






PREMIUM_MULTIPLIER = 1.5



STOP_LOSS_MULTIPLIER = 8






#########################HENDRIK#########################

# Minimum Premium
PREMIUM_THRESHOLD = 0.1

# Maximum Premium
MAX_PREMIUM = 111

# Enable/Disable Profit take
USE_PROFIT = True

# Enable/Disable Timed exit
USE_TIMED_EXIT = False

# Exit Time
EXIT_TIME = time(12, 0).strftime("%-H%-M")


PROFIT_PERCENT = 90

AMOUNT_OF_CONTRACTS = 10

# Minimum range from open
MINIMUM_DISTANCE = 0.025

# Maximum range from open
RANGE_MAX = 0.027

# Use ATR to lower Threshold (If ATR value is below ATR Threshold reduce range to new ranges)

USE_SMA = True
SMA_LENGTH = 200
SMA_MINIMUM_DISTANCE = 0.02


USE_ATR = True
ATR_THRESHOLD = 0.02
NEW_MINIMUM_DISTANCE = 0.02
NEW_RANGE_MAX = 0.022

USE_VIX_ATR = True
VIX_ATR_MINIMUM_DISTANCE = 0.015
VIX_ATR_RANGE_MAX = 0.017



# Use Vix to decide to take a trade or not
USE_VIX = True
VIX_THRESHOLD = 25


USE_VIX_2 = True
VIX_THRESHOLD_2 = 30
VIX_MINIMUM_RANGE = 0.03
VIX_RANGE_MAX = 0.032


PREMIUM_1_5 = 0.10
PREMIUM_2 = 0.10
PREMIUM_2_5 = 0.10
PREMIUM_3 = 0.10

#########################HENDRIK#########################







PREMIUM_RANGE_RATIO = 10

AVG_DAYS = 14

USE_5_5 = False

NEW_THRESHOLD = 0.25


ALLOW_RE_ENTER = False

MINUTES_TO_LOWER_THRESHOLD = 180
LOWERED_THRESHOLD = 0.1


USE_AVG = False



STRIKE_MAX = 5
RANGE_WEIGHT = 0.05 
STRIKE_WEIGHT = 0.2 






# LOOK UP



START = 1
INCREMENT = 1
END = 5
MAX_PERCENT = 0.027
from AlgorithmImports import *
from itertools import count
from collections import deque
from QuantConnect.Securities.Option import OptionPriceModels
import config
import statistics as stats
import requests
import time
from bar_change import BarChange


class SmoothFluorescentYellowCaribou(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2021, 1, 1)  # Set Start Date
        self.SetEndDate(2021, 12, 31)
        self.SetCash(1000000)  # Set Strategy Cash
        #self.Settings.DataSubscriptionLimit = 300
        self.Spy = self.AddEquity("SPY", Resolution.Minute, extendedMarketHours=False).Symbol
        self.VIX = self.AddIndex("VIX", Resolution.Minute).Symbol
        self.option = self.AddOption(self.Spy, Resolution.Minute)
        self.option.SetLeverage(1.0)


        self.Bar_Change = BarChange(self, self.Spy)

        self.Premium_Multiplier = config.PREMIUM_MULTIPLIER

        self.List_Of_Perentages = config.LIST_OF_PERCENTAGES
        self.List_Of_Gaps = config.LIST_OF_GAPS

        self.option_symbol = self.option.Symbol
        self.option.PriceModel = OptionPriceModels.CrankNicolsonFD()
        self.atr_5 = NormalizedAverageTrueRange(5)
        self.atr_14 = NormalizedAverageTrueRange(14)
        self.atr_21 = NormalizedAverageTrueRange(21)
        self.atr_42 = NormalizedAverageTrueRange(42)
        self.atr_63 = NormalizedAverageTrueRange(63)


        self.Bar_Consolidator = TradeBarConsolidator(timedelta(days=1))
        self.SubscriptionManager.AddConsolidator(self.Spy, self.Bar_Consolidator)
        self.Bar_Consolidator.DataConsolidated += self.Update_ATRs

        

        self.HOD = 0
        self.LOD = 0

        history = self.History[TradeBar](self.Spy, 200, Resolution.Daily)


        for bar in history:
            self.Bar_Consolidator.Update(bar)

        self.Start_Time = time.perf_counter()


        self.option.SetFilter(self.UniverseFunc)
        self.Iron_Condor_Counter = 0
        self.Friday_Window = False
        self.Wednesday_Window = True
        self.Monday_Window = False

        self.Indicator_Average_Call_Deque = deque(maxlen=10)
        self.Indicator_Average_Put_Deque = deque(maxlen=10)

        self.Indicator_Average_Call = 0
        self.Indicator_Average_Put = 0

        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(9, 30), self.Open_Friday_Window)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(15, 59), self.Close_Friday_Window)


        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(9, 30), self.Open_Monday_Window)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(15, 59), self.Close_Monday_Window)

        self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(9, 30), self.Open_Wednesday_Window)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(15, 59), self.Close_Wednesday_Window)


        self.Schedule.On(self.DateRules.On(2022, 2, 23), self.TimeRules.AfterMarketOpen("SPY", 1), self.Close_It)



        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(10,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(11,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(12,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(13,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(14,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(15,0), self.May_Debug)

        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(10,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(11,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(12,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(13,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(14,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.At(15,0), self.May_Debug)

        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(10,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(11,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(12,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(13,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(14,0), self.May_Debug)
        # self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(15,0), self.May_Debug)

      



        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.AfterMarketOpen("SPY", 1), self.Get_Open_Price)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.AfterMarketOpen("SPY", 1), self.Get_Open_Price)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.AfterMarketOpen("SPY", 1), self.Get_Open_Price)



        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.AfterMarketOpen("SPY", 2), self.Get_Open_Price_2)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.AfterMarketOpen("SPY", 2), self.Get_Open_Price_2)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.AfterMarketOpen("SPY", 2), self.Get_Open_Price_2)



        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.BeforeMarketClose("SPY", 1), self.Check_At_Loss)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Wednesday), self.TimeRules.BeforeMarketClose("SPY", 1), self.Check_At_Loss)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.BeforeMarketClose("SPY", 1), self.Check_At_Loss)


        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen("SPY", 5), self.Get_Average)


        self.Traded_Today = False
        
        self.Minimum_Gap = config.MINIMUM_GAP
        self.Maximum_Gap = config.MAXIMUM_GAP
        self.Premium_Threshold = config.PREMIUM_THRESHOLD

        self.Range_Dictionary = {}

        self.Iron_Condors = {}

        self.Counter = 0


        self.Put_Buy_Strike = None
        self.Put_Sell_Strike = None
        self.Call_Buy_Strike = None
        self.Call_Sell_Strike = None


        self.Schedule.On(self.DateRules.EveryDay(), 
                self.TimeRules.Every(timedelta(minutes=31)),
                self.Reset_Counter)

        self.List_Of_Len = []
        self.Previous_Len = 0

        self.Stop_Loss_Multiplier = config.STOP_LOSS_MULTIPLIER
        self.Profit_Percent = 1 - (config.PROFIT_PERCENT/100)
        self.Amount_Of_Contracts = config.AMOUNT_OF_CONTRACTS


        self.Invested_Condor = None
        self.Previous_Fees = None
        self.Max_Unrealized_Loss = 0
        self.Max_Loss_Dollar = 0
        self.Unrealized_Losses = {}
        self.List_Of_Max_Unrealized = []
        self.List_Of_Losses = []
        self.Max_Loss = 0
        self.Avg_Loss = 0


        self.Entered = False


        self.Launched_After_Open = False
        self.Open_Price = None

        self.Allow_Getting_Average = False
        self.Populated_List = False
        self.Len_List = None
        self.Average_Premium = None
        self.Premium_At_Open = None

        self.Premium_List = deque(maxlen=config.AVG_DAYS)
        self.Current_Average = None
        self.Appended_Today = False
        self.Ran_Universe_Func_Today = False
        self.Put_Combinations = {}
        self.Call_Combinations = {}
        self.Created_Combinations_Today = False
        self.Previous_Average = None
        self.Monday_Premium_Queue = deque(maxlen=5)
        self.Wednesday_Premium_Queue = deque(maxlen=5)
        self.Friday_Premium_Queue = deque(maxlen=5)
        self.Dont_Enter = False
        self.all_iv = 0
        self.Premium_At_Open_2 = None
        self.Appended_Today_2 = False


        self.List_To_Look_Up = []

        self.Allow_Re_enter = config.ALLOW_RE_ENTER
        self.Entered_With_PT = False
       

        self.Condor_List = []
        self.Sorted_Today = False
        self.Averaged_Down = False
        self.Avg_Down_Time = None
        self.VIX_Open = None
        self.Trade_Counter = 0
        self.Print_Out = False

        self.Minimum_Distance = config.MINIMUM_DISTANCE
        self.Range_Max = config.RANGE_MAX
    



    def Update_ATRs(self, sender, bar):
        self.atr_5.Update(bar)
        self.atr_14.Update(bar)
        self.atr_21.Update(bar)
        self.atr_42.Update(bar)
        self.atr_63.Update(bar)


    def Get_Average(self):
        self.Allow_Getting_Average = True


    def Check_At_Loss(self):
        if self.Invested_Condor is not None:
            if self.Time.month == 3:
                self.Debug(f"{self.Securities[self.Spy].High} {self.Securities[self.Spy].Low} {self.Invested_Condor.Call_Sell.Strike} {self.Invested_Condor.Put_Sell.Strike}")
            if self.Securities[self.Spy].High+0.1 >= self.Invested_Condor.Call_Sell.Strike:
                self.Liquidate()
            elif self.Securities[self.Spy].Low-0.1 <= self.Invested_Condor.Put_Sell.Strike:
                self.Liquidate()



    def Get_Open_Price(self):
     
        if config.USE_PRINT_OUT and self.Time.strftime("%Y%-m%-d") in config.PRINT_OUT:
            self.Print_Out = True
        self.Open_Price = self.Securities[self.Spy].Open
        #self.Debug(f"Open {self.Open_Price}")
        #self.VIX_Open = self.Securities[self.VIX].Open
        #self.Debug(self.Time)
    

    def Get_Open_Price_2(self):
        if self.Open_Price is None:
            self.Open_Price = self.Securities[self.Spy].Open

    def Close_It(self):
        self.Monday_Window = False
        self.Wednesday_Window = False
        self.Friday_Window = False

    

    def Record_Premium_At_Open(self, premium):
        if self.Time.weekday() == 0:
            self.Monday_Premium_Queue.appendleft(premium)
        elif self.Time.weekday() == 2:
            self.Wednesday_Premium_Queue.appendleft(premium)
        elif self.Time.weekday() == 4:
            self.Friday_Premium_Queue.appendleft(premium)




    def Reset_Counter(self):
        for x in self.Iron_Condors.keys():
            condor = self.Iron_Condors[x]
            condor.Sent_Already = False
            condor.Scanned_Already = False
        self.Counter = 0


    def Open_Monday_Window(self):
        #self.Debug(f"{self.Time} VIX {self.Securities[self.VIX].Open}")
        self.Appended_Today = False
        self.Put_Buy_Strike = None
        self.Put_Sell_Strike = None
        self.Call_Buy_Strike = None
        self.Call_Sell_Strike = None
        self.Call_Strike = None
        self.Put_Strike = None
        self.Monday_Window = True
        self.Previous_Fees = self.Portfolio.TotalFees
        self.Invested_Condor = None
        self.Traded_Today = False
        self.Previous_AccountValue = self.Portfolio.TotalPortfolioValue
        if config.USE_FOMC_MINUTES:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MINUTES:
                self.Dont_Enter = True
        if config.USE_FOMC_MEETINGS:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MEETINGS:
                self.Dont_Enter = True
        if config.USE_CPI:
            if self.Time.strftime("%Y%-m%-d") in config.CPI:
                self.Dont_Enter = True
        if config.USE_CPI_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.CPI_NEXTDAY:
                self.Dont_Enter = True
        if config.USE_POWELL:
            if self.Time.strftime("%Y%-m%-d") in config.POWELL:
                self.Dont_Enter = True
        if config.USE_POWELL_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.POWELL_NEXTDAY:
                self.Dont_Enter = True
        if config.USE_FED_INTEREST_RATE_DECISION:
            if self.Time.strftime("%Y%-m%-d") in config.FED_INTEREST_RATE_DECISION:
                self.Dont_Enter = True
        if config.USE_FED_INTEREST_RATE_DECISION_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.FED_INTEREST_RATE_DECISION_NEXTDAY:
                self.Dont_Enter = True     
        if config.USE_FOMC_MEETINGS_FIRSTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MEETINGS_FIRSTDAY:
                self.Dont_Enter = True                            



    
    def Open_Wednesday_Window(self):
        self.Appended_Today = False
        self.Put_Buy_Strike = None
        self.Put_Sell_Strike = None
        self.Call_Buy_Strike = None
        self.Call_Sell_Strike = None
        self.Call_Strike = None
        self.Put_Strike = None
        self.Wednesday_Window = True
        self.Previous_Fees = self.Portfolio.TotalFees
        self.Invested_Condor = None
        self.Traded_Today = False
        self.Previous_AccountValue = self.Portfolio.TotalPortfolioValue
        if config.USE_FOMC_MINUTES:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MINUTES:
                self.Dont_Enter = True
        if config.USE_FOMC_MEETINGS:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MEETINGS:
                self.Dont_Enter = True
        if config.USE_CPI:
            if self.Time.strftime("%Y%-m%-d") in config.CPI:
                self.Dont_Enter = True
        if config.USE_CPI_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.CPI_NEXTDAY:
                self.Dont_Enter = True
        if config.USE_POWELL:
            if self.Time.strftime("%Y%-m%-d") in config.POWELL:
                self.Dont_Enter = True
        if config.USE_POWELL_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.POWELL_NEXTDAY:
                self.Dont_Enter = True
        if config.USE_FED_INTEREST_RATE_DECISION:
            if self.Time.strftime("%Y%-m%-d") in config.FED_INTEREST_RATE_DECISION:
                self.Dont_Enter = True
        if config.USE_FED_INTEREST_RATE_DECISION_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.FED_INTEREST_RATE_DECISION_NEXTDAY:
                self.Dont_Enter = True  
        if config.USE_FOMC_MEETINGS_FIRSTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MEETINGS_FIRSTDAY:
                self.Dont_Enter = True  




    def Open_Friday_Window(self):
        self.Appended_Today = False
        self.Put_Buy_Strike = None
        self.Put_Sell_Strike = None
        self.Call_Buy_Strike = None
        self.Call_Sell_Strike = None
        self.Call_Strike = None
        self.Put_Strike = None
        self.Friday_Window = True
        self.Previous_Fees = self.Portfolio.TotalFees
        self.Invested_Condor = None
        self.Traded_Today = False
        self.Previous_AccountValue = self.Portfolio.TotalPortfolioValue

        if config.USE_FOMC_MINUTES:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MINUTES:
                self.Dont_Enter = True
        if config.USE_FOMC_MEETINGS:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MEETINGS:
                self.Dont_Enter = True
        if config.USE_CPI:
            if self.Time.strftime("%Y%-m%-d") in config.CPI:
                self.Dont_Enter = True
        if config.USE_CPI_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.CPI_NEXTDAY:
                self.Dont_Enter = True
        if config.USE_POWELL:
            if self.Time.strftime("%Y%-m%-d") in config.POWELL:
                self.Dont_Enter = True
        if config.USE_POWELL_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.POWELL_NEXTDAY:
                self.Dont_Enter = True
        if config.USE_FED_INTEREST_RATE_DECISION:
            if self.Time.strftime("%Y%-m%-d") in config.FED_INTEREST_RATE_DECISION:
                self.Dont_Enter = True
        if config.USE_FED_INTEREST_RATE_DECISION_NEXTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.FED_INTEREST_RATE_DECISION_NEXTDAY:
                self.Dont_Enter = True  
        if config.USE_FOMC_MEETINGS_FIRSTDAY:
            if self.Time.strftime("%Y%-m%-d") in config.FOMC_MEETINGS_FIRSTDAY:
                self.Dont_Enter = True  

    def OnEndOfAlgorithm(self):
        end_time = time.perf_counter()
        #self.Debug(f"Ran the Algo in {end_time - self.Start_Time:0.4f} seconds VIX {self.Securities[self.VIX].Price} {self.Securities[self.VIX].Close} {self.Time}")


  
        #self.Debug(self.Unrealized_Losses)

    #     avg_loss = stats.mean(self.List_Of_Losses)
    #     max_realized_loss = min(self.List_Of_Losses)
    #     max_unrealized_loss = max(self.List_Of_Max_Unrealized)
        #loss_count = len(self.List_Of_Losses)

        #self.Debug(f"avg loss {avg_loss} max loss {max_realized_loss} max unrealized loss {max_unrealized_loss} loss count {loss_count}")
        self.Debug(self.List_Of_Losses)
        wins = self.Trade_Counter - len(self.List_Of_Losses)
        winrate = wins / self.Trade_Counter
        losses = len(self.List_Of_Losses)
        self.Debug(f"Winrate {winrate*100}%  Total Trades {self.Trade_Counter} Total Losses {losses}")
    #     self.Debug(f"Counter {self.Iron_Condor_Counter}")


    def Close_Monday_Window(self):
        self.Print_Out = False
        self.Entered = False
        self.Averaged_Down = False
        time = self.Time.strftime("%y %b %d %a")
        string_1 = str(self.Max_Unrealized_Loss)
        string_2 = str(self.Max_Loss_Dollar)
        string_3 = string_1 + "/" + string_2
        
        self.Unrealized_Losses[time] = string_3
        self.Monday_Window = False
        self.Sent_Already = []
        self.Iron_Condors.clear()
        self.List_Of_Max_Unrealized.append(self.Max_Loss_Dollar)
        self.Max_Unrealized_Loss = 0
        self.Max_Loss_Dollar = 0
        account_value = self.Portfolio.TotalPortfolioValue
        pnl = account_value - self.Previous_AccountValue
        close_price = self.Securities[self.Spy].Close
        if self.Open_Price is None:
           
            start_time = self.Time - timedelta(minutes=350)
            end_time = self.Time - timedelta(minutes=330)
            history = self.History[TradeBar](self.Spy, start_time, end_time, Resolution.Minute)
          
            for bar in history:
                self.Debug(f" wtf {bar.Open}")
                self.Open_Price = bar.Open
        if self.Open_Price is not None:
            range_today = (self.Open_Price - close_price) / self.Open_Price
            range_today = round(range_today, 3)
        else:
            range_today = 0
        atr_5 = self.atr_5.Current.Value
        atr_14 = self.atr_14.Current.Value
        atr_21 = self.atr_21.Current.Value
        atr_42 = self.atr_42.Current.Value
        atr_63 = self.atr_63.Current.Value

        # full_range =  ((self.HOD - self.LOD) / close_price)


        # string_debug = f"Date {time} Trade Result {pnl} Range OC {range_today} Range HL {full_range} Premium 2% {self.Premium_At_Open_2} Premium 2.5% {self.Premium_At_Open} IV {self.all_iv} ATR 5 {atr_5} ATR 14 {atr_14} ATR 21 {atr_21} ATR 42 {atr_42} ATR 63 {atr_63}"
        #self.Debug(string_debug)
        self.all_iv = 0
        self.Premium_At_Open_2 = None
        self.Appended_Today_2 = False
        self.Len_List = None
        self.Average_Premium = None
        self.Populated_List = False
        self.Open_Price = None
        self.Premium_At_Open = None
        self.Ran_Universe_Func_Today = False
        self.Put_Combinations.clear()
        self.Call_Combinations.clear()
        self.Created_Combinations_Today = False
        self.Dont_Enter = False
        self.Entered_With_PT = False
        self.Sorted_Today = False
        self.Condor_List.clear()
        self.List_To_Look_Up.clear()
        self.HOD = 0
        self.LOD = 0
        
     
        if pnl < 0:
            self.List_Of_Losses.append((pnl, time))
        
     

    

    def Close_Wednesday_Window(self):
        self.Print_Out = False
        self.Entered = False
        self.Averaged_Down = False
        time = self.Time.strftime("%y %b %d %a")
        string_1 = str(self.Max_Unrealized_Loss)
        string_2 = str(self.Max_Loss_Dollar)
        string_3 = string_1 + "/" + string_2
       
        self.Unrealized_Losses[time] = string_3
        self.Wednesday_Window = False
        self.Sent_Already = []
        self.Iron_Condors.clear()
        self.List_Of_Max_Unrealized.append(self.Max_Loss_Dollar)
        self.Max_Unrealized_Loss = 0
        self.Max_Loss_Dollar = 0
        account_value = self.Portfolio.TotalPortfolioValue
        pnl = account_value - self.Previous_AccountValue
        close_price = self.Securities[self.Spy].Close
        if self.Open_Price is not None:
            range_today = (self.Open_Price - close_price) / self.Open_Price
            range_today = round(range_today, 3)
        else:
            range_today = 0
        atr_5 = self.atr_5.Current.Value
        atr_14 = self.atr_14.Current.Value
        atr_21 = self.atr_21.Current.Value
        atr_42 = self.atr_42.Current.Value
        atr_63 = self.atr_63.Current.Value

        # full_range = ((self.HOD - self.LOD) / close_price)


        # string_debug = f"Date {time} Trade Result {pnl} Range OC {range_today} Range HL {full_range} Premium 2% {self.Premium_At_Open_2} Premium 2.5% {self.Premium_At_Open} IV {self.all_iv} ATR 5 {atr_5} ATR 14 {atr_14} ATR 21 {atr_21} ATR 42 {atr_42} ATR 63 {atr_63}"
        #self.Debug(string_debug)
        self.all_iv = 0
        self.Premium_At_Open_2 = None
        self.Appended_Today_2 = False
        self.Len_List = None
        self.Average_Premium = None
        self.Populated_List = False
        self.Open_Price = None
        self.Premium_At_Open = None
        self.Ran_Universe_Func_Today = False
        self.Put_Combinations.clear()
        self.Call_Combinations.clear()
        self.Created_Combinations_Today = False
        self.Dont_Enter = False
        self.Entered_With_PT = False
        self.Sorted_Today = False
        self.Condor_List.clear()
        self.List_To_Look_Up.clear()
        self.HOD = 0
        self.LOD = 0
    
        if pnl < 0:
            self.List_Of_Losses.append((pnl, time))
        
    

    def Close_Friday_Window(self):
        self.Print_Out = False
        self.Entered = False
        self.Averaged_Down = False
        time = self.Time.strftime("%y %b %d %a")
        string_1 = str(self.Max_Unrealized_Loss)
        string_2 = str(self.Max_Loss_Dollar)
        string_3 = string_1 + "/" + string_2
     
        self.Unrealized_Losses[time] = string_3
        self.Friday_Window = False
        self.Sent_Already = []
       
        self.Iron_Condors.clear()
        self.List_Of_Max_Unrealized.append(self.Max_Loss_Dollar)
        self.Max_Unrealized_Loss = 0
        self.Max_Loss_Dollar = 0
        account_value = self.Portfolio.TotalPortfolioValue
        pnl = account_value - self.Previous_AccountValue
        if self.Open_Price is None:
            start_time = self.Time - timedelta(minutes=390)
            history = self.History[TradeBar](self.Spy, start_time, start_time, Resolution.Minute)
            for bar in history:
                self.Open_Price = bar.Open

        close_price = self.Securities[self.Spy].Close
        if self.Open_Price is not None:
            range_today = (self.Open_Price - close_price) / self.Open_Price
            range_today = round(range_today, 3)
        else:
            range_today = 0
        atr_5 = self.atr_5.Current.Value
        atr_14 = self.atr_14.Current.Value
        atr_21 = self.atr_21.Current.Value
        atr_42 = self.atr_42.Current.Value
        atr_63 = self.atr_63.Current.Value
        # full_range = ((self.HOD - self.LOD) / close_price)


        # string_debug = f"Date {time} Trade Result {pnl} Range OC {range_today} Range HL {full_range} Premium 2% {self.Premium_At_Open_2} Premium 2.5% {self.Premium_At_Open} IV {self.all_iv} ATR 5 {atr_5} ATR 14 {atr_14} ATR 21 {atr_21} ATR 42 {atr_42} ATR 63 {atr_63}"
        #self.Debug(string_debug)
        self.all_iv = 0
        self.Premium_At_Open_2 = None
        self.Appended_Today_2 = False
        self.Len_List = None
        self.Average_Premium = None
        self.Populated_List = False
        self.Open_Price = None
        self.Premium_At_Open = None
        self.Ran_Universe_Func_Today = False
        self.Put_Combinations.clear()
        self.Call_Combinations.clear()
        self.Created_Combinations_Today = False
        self.Dont_Enter = False
        self.Entered_With_PT = False
        self.Sorted_Today = False
        self.Condor_List.clear()
        self.List_To_Look_Up.clear()
        self.HOD = 0
        self.LOD = 0

        if pnl < 0:
            self.List_Of_Losses.append((pnl, time))
        
    # def May_Debug(self):
    #     current_hour = str(self.Time.hour)
    #     #self.Debug(f"{self.Time} Premium {self.Premium_At_Open}")
    #     list_sums_oc = self.Bar_Change.Relative_OC[current_hour]
    #     list_sums_hl = self.Bar_Change.Relative_HL[current_hour]
    #     sum_oc, relative_oc, ratio_oc, sum_hl, relative_hl, ratio_hl = self.Bar_Change.Get_Relative_Change(list_sums_oc, list_sums_hl)

        #if ratio_oc >= 2 or ratio_hl >= 2:
            #self.Debug(f"{self.Time} sum_oc {sum_oc} relative_oc {relative_oc} ratio_oc {ratio_oc} sum_hl {sum_hl} relative_hl {relative_hl} ratio_hl {ratio_hl}")

    def Get_Max_Unrealized_Loss(self, current_profit):
        if self.Max_Unrealized_Loss == 0:
            
            if self.Invested_Condor.Profit == 0:
                return

            if current_profit > self.Invested_Condor.Profit:
                self.Max_Unrealized_Loss = abs(current_profit)/self.Invested_Condor.Profit
        
        if self.Max_Unrealized_Loss != 0:
         
            x = abs(current_profit)/self.Invested_Condor.Profit
            if x > self.Max_Unrealized_Loss:
                self.Max_Unrealized_Loss = x
                self.Max_Loss_Dollar = abs(current_profit) - self.Invested_Condor.Profit



    def Profit_Taker(self):
        
     

        


        if self.Invested_Condor.Current_Profit <= self.Profit_Percent * self.Invested_Condor.Entry_Premium:
            if self.Portfolio.Invested:
                self.Liquidate(tag="PROFIT TAKER")
                #self.Debug(f"{self.Time} Entry {self.Invested_Condor.Entry_Premium} PROFIT TAKEN {self.Invested_Condor.Current_Profit}")
                self.Entered_With_PT = False
                self.Invested_Condor.Profit_Taken = True
               
                self.Invested_Condor.Sent_Already = False
                self.Invested_Condor.Premium = None
                self.Invested_Condor.Entry_Premium = None
                self.Invested_Condor.Entry_Fees = None

                self.Invested_Condor.Lowest_Premium = None
                self.Invested_Condor.Scanned_Already = False

                self.Invested_Condor.Profit = None
                self.Invested_Condor.Stopped_Out = False
                self.Invested_Condor.Profit_Taken = False
                
                self.Invested_Condor.Current_Profit = None
                self.Invested_Condor.Margin_Required = None
                self.Invested_Condor = None
                
                
        

    
    def Stop_Loss(self):
        
        pnl = self.Portfolio.TotalUnrealizedProfit
        max_loss = -(self.Invested_Condor.Profit * self.Stop_Loss_Multiplier)



        if pnl <= max_loss:
            if self.Portfolio.Invested:
                self.Liquidate(tag=f"STOP LOSS {pnl} {max_loss} {self.Invested_Condor.Profit} {self.Invested_Condor.Entry_Premium} {self.Invested_Condor.Current_Profit}")
                self.Invested_Condor.Stopped_Out = True



    def OnData(self, data: Slice):
        #if self.Time.hour == 9 and self.Time.minute == 31:
            #self.Debug(f"{self.Time} VIX {self.Securities[self.VIX].Open}")
        Price = self.Securities[self.Spy].Price
        
        if Price > self.HOD:
            self.HOD = Price

        if self.LOD == 0:
            self.LOD = Price

        if Price < self.LOD:
            self.LOD = Price

        if self.Portfolio.Invested:
            if self.Invested_Condor.Profit is None:
                fees = self.Portfolio.TotalFees - self.Previous_Fees
                initial_profit = (self.Invested_Condor.Entry_Premium * 100) * self.Amount_Of_Contracts
                self.Invested_Condor.Profit = initial_profit - fees
            fees = self.Portfolio.TotalFees - self.Previous_Fees
            current_premium = self.Invested_Condor.Calculate_Premium(self.Securities[self.Invested_Condor.Put_Buy.Symbol].AskPrice, self.Securities[self.Invested_Condor.Put_Sell.Symbol].BidPrice, self.Securities[self.Invested_Condor.Call_Buy.Symbol].AskPrice, self.Securities[self.Invested_Condor.Call_Sell.Symbol].BidPrice)
            current_premium = current_premium 

            self.Invested_Condor.Current_Profit = current_premium 
            if self.Invested_Condor.Entry_Fees is None:
                self.Invested_Condor.Entry_Fees = fees
            self.Get_Max_Unrealized_Loss(self.Invested_Condor.Current_Profit)
            if config.USE_PROFIT:
                self.Profit_Taker()
            #self.Stop_Loss()
        # if self.Portfolio.Invested:
        #     if self.Invested_Condor.Profit is None:
        #         fees = self.Portfolio.TotalFees - self.Previous_Fees
        #         profit = (self.Invested_Condor.Entry_Premium * 100) * self.Amount_Of_Contracts
        #         self.Invested_Condor.Profit = profit - fees
        #     self.Get_Max_Unrealized_Loss()
        #     self.Profit_Taker()
        #     self.Stop_Loss()
        if self.Portfolio.Invested and self.Print_Out:
            x = self.Invested_Condor.Calculate_Premium(self.Securities[self.Invested_Condor.Put_Buy.Symbol].AskPrice, self.Securities[self.Invested_Condor.Put_Sell.Symbol].BidPrice, self.Securities[self.Invested_Condor.Call_Buy.Symbol].AskPrice, self.Securities[self.Invested_Condor.Call_Sell.Symbol].BidPrice)
            percent_range = self.Invested_Condor.open_put_range
            self.Debug(f"{percent_range*100}% Premium {x} {self.Time}")
        if self.Portfolio["SPY"].Invested:
            self.Liquidate("SPY")
        

        if config.USE_TIMED_EXIT and self.Time.strftime("%-H%-M") >= config.EXIT_TIME:
            if self.Portfolio.Invested:
                self.Liquidate()
            return
        vix = self.Securities[self.VIX].Price
        #if config.USE_VIX:
            #if vix > config.VIX_THRESHOLD: return
        if (self.Portfolio.Invested and not self.Allow_Re_enter) or (self.Dont_Enter): return

        for i in data.OptionChains:
            
            # Checking if we are at the right symbol (SPY)
            
           

            if i.Key != self.option_symbol: continue
            optionchain = i.Value
            
            # if option chain is empty return
            
            
            if (data.OptionChains.Count == 0):
                return 

        

            Price = self.Securities[self.Spy].Price
            Price = math.floor(Price)


            if self.Friday_Window or self.Wednesday_Window or self.Monday_Window:
              


                if self.Open_Price is None:
                    self.Debug(f"None {self.Time}")
                    self.Open_Price = self.Securities[self.Spy].Open
           


         



                
                expiry_date = "TODAY"
                if not self.Created_Combinations_Today:

                    List_Of_Distances = []

                    #self.Debug("IN WINDOW")
                    # Grab all put and all call contracts and store them in a list each
                    put_3_expiry = [x for x in optionchain if x.Right == OptionRight.Put and ((x.Expiry - self.Time).days) == -1 and (x.Strike - Price) < 1]
                    call_3_expiry =  [x for x in optionchain if x.Right == OptionRight.Call and ((x.Expiry - self.Time).days) == -1 and (Price - x.Strike) < 1]
                  


                    put_3_min_distance = Price*1
                    put_3_min_distance = math.floor(put_3_min_distance)

                    # Adding all put contracts that are far enough away from current price to a new list
                    put_3_min_distances_sell = [x for x in put_3_expiry]
                    put_3_min_distances_buy = [x for x in put_3_expiry]


                    # Calculate distance of how much lower than current price the strike price for call contracts has to be 
                    # Using minimum percentage distance and then rounding the number up
                    call_3_min_distance = Price*1
                    call_3_min_distance = math.ceil(call_3_min_distance)

                    # Adding all call contracts that are far enough away from current price to a new list
                    call_3_min_distances_sell = [x for x in call_3_expiry]
                    call_3_min_distances_buy = [x for x in call_3_expiry]


                    # Sorting both lists by Strike price, put list will start with the highest puts and call list with the lowest call
                    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)
                    
                  
       
             

                    put_list = []
                    call_list = []

                    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 >= 1 and strike_diff <= 5:
                                combo = (x, y)
                                put_list.append(combo)
                               
                                #if strike_diff < 5:
                                    #self.Debug(f"{self.Time} {strike_diff}")  
             
                    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 >= 1 and strike_diff <= 5: 
                                combo = (x, y)
                                call_list.append(combo)
              
           

                    if config.USE_VIX_ATR and self.atr_21.Current.Value/100 <= config.ATR_THRESHOLD and vix <= config.VIX_THRESHOLD:
                        self.Minimum_Distance = config.VIX_ATR_MINIMUM_DISTANCE
                        self.Range_Max = config.VIX_ATR_RANGE_MAX
                        self.Premium_Threshold = config.PREMIUM_1_5
                        #self.Debug("USING 1.5")
                        self.Plot("Range Used", "Range", config.VIX_ATR_MINIMUM_DISTANCE)
                    elif config.USE_ATR and self.atr_21.Current.Value/100 <= config.ATR_THRESHOLD:
                        self.Minimum_Distance = config.NEW_MINIMUM_DISTANCE
                        self.Range_Max = config.NEW_RANGE_MAX
                        self.Plot("Range Used", "Range", config.NEW_MINIMUM_DISTANCE)
                        self.Premium_Threshold = config.PREMIUM_2
                        #self.Debug("USING 2")
                    elif config.USE_VIX and vix <= config.VIX_THRESHOLD:
                        self.Minimum_Distance = config.NEW_MINIMUM_DISTANCE
                        self.Range_Max = config.NEW_RANGE_MAX
                        self.Plot("Range Used", "Range", config.NEW_MINIMUM_DISTANCE)
                        self.Premium_Threshold = config.PREMIUM_2
                        #self.Debug("USING 2")
                    else:
                        self.Minimum_Distance = config.MINIMUM_DISTANCE
                        self.Range_Max = config.RANGE_MAX
                        self.Plot("Range Used", "Range", config.MINIMUM_DISTANCE)
                        self.Premium_Threshold = config.PREMIUM_2_5
                        #self.Debug("USING 2.5")

                    if config.USE_VIX_2 and vix >= config.VIX_THRESHOLD_2:
                        self.Minimum_Distance = config.VIX_MINIMUM_RANGE
                        self.Range_Max = config.VIX_RANGE_MAX
                        self.Plot("Range Used", "Range", config.VIX_MINIMUM_RANGE)
                        self.Premium_Threshold = config.PREMIUM_3

                    self.Plot("Premium Used", "Premium", self.Premium_Threshold)
                    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:
                                Strikes = f"{pb.Strike} {ps.Strike} {cs.Strike} {cb.Strike}"
                                if Strikes not in self.Iron_Condors and self.Open_Price is not None:
                                    open_call_range = ((cs.Strike - self.Open_Price) / self.Open_Price)
                                    open_put_range = abs((ps.Strike - self.Open_Price) / self.Open_Price)
                                    self.Iron_Condors[Strikes] = Iron_Condor(self, pb, ps, cb, cs, open_call_range, open_put_range)

                                    

                                    if self.Minimum_Distance <= open_call_range <= self.Range_Max and self.Minimum_Distance <= open_put_range <= self.Range_Max:
                                        self.List_To_Look_Up.append(Strikes)
                                        if not self.Appended_Today_2:
                                            

                                            condor = self.Iron_Condors[Strikes]
                                            premium = self.Iron_Condors[Strikes].Calculate_Premium(self.Securities[condor.Put_Buy.Symbol].AskPrice, self.Securities[condor.Put_Sell.Symbol].BidPrice, self.Securities[condor.Call_Buy.Symbol].AskPrice, self.Securities[condor.Call_Sell.Symbol].BidPrice)
                                            #self.Debug(f"Range {open_call_range}")
                                            self.Premium_At_Open_2 = premium
                                            self.Appended_Today_2 = True
                                            #self.Debug(f"2% {premium}")

                                    #if p_diff < 5:
                                        #self.Debug(f"{self.Time} {p_diff}")
                                    #self.Debug(f"ps {ps_strikes} ----------------- pb {pb_strikes} -----------------cs {cs_strikes} -----------------cb {cb_strikes}")
                                    weight = self.Assign_Weighting(open_call_range, open_put_range, p_diff)


                                    self.Iron_Condors[Strikes].Weight = weight


                                    if open_call_range >= 0.024 and open_call_range < 0.027 and open_put_range >= 0.024 and open_put_range < 0.027:
                                        #self.Debug(f"{open_call_range} {open_put_range}")
                                        condor = self.Iron_Condors[Strikes]
                                        premium = self.Iron_Condors[Strikes].Calculate_Premium(self.Securities[condor.Put_Buy.Symbol].AskPrice, self.Securities[condor.Put_Sell.Symbol].BidPrice, self.Securities[condor.Call_Buy.Symbol].AskPrice, self.Securities[condor.Call_Sell.Symbol].BidPrice)
                                       
                                        
                                        if not self.Appended_Today:
                                            self.Premium_At_Open = premium
                                            #self.Debug(f"2.5% {premium}")
                                            self.Premium_List.appendleft(premium)
                                            self.Appended_Today = True
                                            self.Record_Premium_At_Open(premium)
                                            iv_cs = cs.ImpliedVolatility
                                            iv_cb = cb.ImpliedVolatility
                                            iv_ps = ps.ImpliedVolatility
                                            iv_pb = pb.ImpliedVolatility
                                            iv_list = [iv_cs, iv_cb, iv_ps, iv_pb]
                                            self.all_iv = stats.mean(iv_list)
                                            #if all_iv != 0:
                                                #self.Debug(f"{self.Time} {all_iv}")
                                   
             
                    for x in self.Iron_Condors.keys():
                        condor = self.Iron_Condors[x]
                        self.Condor_List.append((condor.Weight, condor))

                    self.Condor_List.sort(key=lambda x: x[0], reverse = True)




                    for x in self.Condor_List:
                        condor = x[1]
                        if condor.Calculate_Premium(self.Securities[condor.Put_Buy.Symbol].AskPrice, self.Securities[condor.Put_Sell.Symbol].BidPrice, self.Securities[condor.Call_Buy.Symbol].AskPrice, self.Securities[condor.Call_Sell.Symbol].BidPrice) >= 0.07:
                            self.Indicator_Average_Call_Deque.appendleft(condor.open_call_range)
                            self.Indicator_Average_Put_Deque.appendleft(condor.open_put_range)

                            if len(self.Indicator_Average_Call_Deque) == 10 and len(self.Indicator_Average_Put_Deque) == 10:
                                self.Indicator_Average_Call = sum(self.Indicator_Average_Call_Deque) / len(self.Indicator_Average_Call_Deque)
                                self.Indicator_Average_Put = sum(self.Indicator_Average_Put_Deque) / len(self.Indicator_Average_Put_Deque)
                            break




                    self.Created_Combinations_Today = True
                    put_list.clear()
                    call_list.clear()
                    put_3_expiry.clear()
                    call_3_expiry.clear()
                    put_3_min_distances_buy.clear()
                    put_3_min_distances_sell.clear()
                    put_3_min_distances_sorted_buy.clear()
                    put_3_min_distances_sorted_sell.clear()
                    call_3_min_distances_buy.clear()
                    call_3_min_distances_sell.clear()
                    call_3_min_distances_sorted_buy.clear()
                    call_3_min_distances_sorted_sell.clear()

                    #self.Debug(len(self.List_To_Look_Up))

                premium_list = []
              

              


                if len(self.Premium_List) == config.AVG_DAYS:
                    self.Current_Average = stats.mean(self.Premium_List)

                if not self.Portfolio.Invested or (self.Portfolio.Invested and self.Allow_Re_enter and not self.Averaged_Down):
                    if not self.Entered_With_PT and not self.Portfolio.Invested or (self.Portfolio.Invested and self.Allow_Re_enter and not self.Averaged_Down):
                        for x in self.List_To_Look_Up:

                            condor = self.Iron_Condors[x]
                            if not condor.Sent_Already:
                            
                                condor_distance_put = self.Securities[self.Spy].Price - condor.Put_Sell.Strike
                                condor_distance_call = condor.Call_Sell.Strike - self.Securities[self.Spy].Price
                                put_call_distance = abs(condor_distance_put - condor_distance_call)
                                strike_Gap = condor.Call_Buy.Strike - condor.Call_Buy.Strike
                                percentage_call = ((condor.Call_Sell.Strike - self.Securities[self.Spy].Price) / self.Securities[self.Spy].Price)

                                percentage_put = ((self.Securities[self.Spy].Price - condor.Put_Sell.Strike) / condor.Put_Sell.Strike)
                                #if self.Counter >= 15:
                                    #self.Premium_Threshold = 0.25
                                #else:
                                    #self.Premium_Threshold = config.PREMIUM_THRESHOLD
                                
                                percentage = ((abs(self.Securities[self.Spy].Price - condor.Put_Sell.Strike) / self.Securities[self.Spy].Price) + (abs(self.Securities[self.Spy].Price - condor.Call_Sell.Strike) / self.Securities[self.Spy].Price)) / 2

                            

                                
                             
                            
                            if config.USE_5_5:
                                if self.Time.weekday() == 0 and len(self.Monday_Premium_Queue) == 5:
                                    premiums = self.Premium_List + self.Monday_Premium_Queue
                                    self.Current_Average = stats.mean(premiums)
                                elif self.Time.weekday() == 2 and len(self.Wednesday_Premium_Queue) == 5:
                                    premiums = self.Premium_List + self.Wednesday_Premium_Queue
                                    self.Current_Average = stats.mean(premiums)
                                elif self.Time.weekday() == 4 and len(self.Friday_Premium_Queue) == 5:
                                    premiums = self.Premium_List + self.Friday_Premium_Queue
                                    self.Current_Average = stats.mean(premiums)
                            

                            if self.Current_Average != 0 and self.Current_Average is not None:
                                self.Previous_Average = self.Current_Average

                            if config.USE_AVG:
                                if self.Current_Average is not None and self.Premium_At_Open is not None:
                                    if self.Premium_At_Open > self.Current_Average:
                                        if self.Current_Average != 0 and self.Premium_At_Open != 0:
                                            premium_higher_by = (abs(self.Premium_At_Open-self.Current_Average)) / self.Current_Average
                                        elif self.Current_Average == 0 and self.Premium_At_Open != 0:
                                            premium_higher_by = (abs(self.Premium_At_Open-self.Previous_Average)) / self.Previous_Average
                                        elif self.Premium_At_Open == 0:
                                            premium_higher_by = 0.0000001



                                        distance_increase_factor = 1 + (abs(premium_higher_by) / config.PREMIUM_RANGE_RATIO)
                                        self.Minimum_Distance = min((self.Minimum_Distance * distance_increase_factor),0.034)
                                        
                                    else:
                                        self.Minimum_Distance = config.MINIMUM_DISTANCE


                            #if self.Entered:
                                #self.Premium_Threshold = config.NEW_THRESHOLD
                            
                            if self.Avg_Down_Time is not None and (self.Avg_Down_Time + timedelta(minutes=config.MINUTES_TO_LOWER_THRESHOLD)) >= self.Time:
                                self.Premium_Threshold = config.LOWERED_THRESHOLD
                            
                                #if self.Traded_Today and config.USE_LOWER_THRESHOLD:
                                    #self.Premium_Threshold = config.NEW_THRESHOLD
                                #else:
                                    #self.Premium_Threshold = config.PREMIUM_THRESHOLD
                            strike_Gap = condor.Call_Buy.Strike - condor.Call_Sell.Strike 
                            #self.Debug(self.Time) 
                            ssss = condor.Calculate_Premium(self.Securities[condor.Put_Buy.Symbol].AskPrice, self.Securities[condor.Put_Sell.Symbol].BidPrice, self.Securities[condor.Call_Buy.Symbol].AskPrice, self.Securities[condor.Call_Sell.Symbol].BidPrice)  
                            #self.Debug(f"{ssss} {condor.open_put_range} {strike_Gap} {config.MAX_PREMIUM} {self.Premium_Threshold} {self.Dont_Enter} {self.Minimum_Distance}")   
                            if strike_Gap <= 5 and config.MAX_PREMIUM >= condor.Calculate_Premium(self.Securities[condor.Put_Buy.Symbol].AskPrice, self.Securities[condor.Put_Sell.Symbol].BidPrice, self.Securities[condor.Call_Buy.Symbol].AskPrice, self.Securities[condor.Call_Sell.Symbol].BidPrice) >= self.Premium_Threshold and condor.open_call_range >= self.Minimum_Distance and condor.open_put_range >= self.Minimum_Distance and not self.Dont_Enter:
                                percentage_call_ = ((condor.Call_Sell.Strike - self.Securities[self.Spy].Price) / self.Securities[self.Spy].Price)

                                percentage_put_ = ((self.Securities[self.Spy].Price - condor.Put_Sell.Strike) / condor.Put_Sell.Strike)

                                #self.Debug("HERE")
                            
                                percentage_call_ = round(percentage_call_, 3)
                                percentage_put_ = round(percentage_put_, 3)


                            
                                Breakeven_Price_Call = condor.Call_Sell.Strike + condor.Premium
                                Breakeven_Price_Put = condor.Put_Sell.Strike - condor.Premium

                                id_ = "-723291833"
                                message__ = f" THIS IS AN ALERT USING RANGE FROM OPEN \n PUT RANGE %{condor.open_put_range} FROM OPEN \n CALL RANGE %{condor.open_call_range} FROM OPEN \n Action   Expiry   Strike   Type \n Sell {(condor.Put_Sell.Expiry).strftime('%b%d%-y')}   ${condor.Put_Sell.Strike}   Put \n Buy {(condor.Put_Buy.Expiry).strftime('%b%d%-y')}   ${condor.Put_Buy.Strike}   Put \n Buy {(condor.Call_Buy.Expiry).strftime('%b%d%-y') }   ${condor.Call_Buy.Strike}   Call \n Sell {(condor.Call_Sell.Expiry).strftime('%b%d%-y')}   ${condor.Call_Sell.Strike}   Call \n \n \n \n Price ${self.Securities[self.Spy].Price} \n  Premium {condor.Premium} \n Strike diff ${abs(condor.Put_Sell.Strike - condor.Put_Buy.Strike)} \n Breakeven Price Call {Breakeven_Price_Call} \n Breakeven Price Put {Breakeven_Price_Put} \n Current Call %{percentage_call_} \n Current Put %{percentage_put_}  \n expiry {expiry_date}"
                                token_ = "5616527268:AAGkUitVosgYOntpLb_JU5HK_SSXm86GsVs"
                                #self.Debug(message__)
                
                                if not condor.Stopped_Out:
                                    if not condor.Profit_Taken or self.Allow_Re_enter:
                                        if not self.Traded_Today or self.Allow_Re_enter:
                                            if not self.Entered_With_PT and not self.Portfolio.Invested or self.Allow_Re_enter:
                                                #self.Notify.Telegram(id=id_, message=message__, token=token_)
                                                
                                                # condor.Sent_Open_Range = True
                                                if self.Portfolio.Invested:
                                                    
                                                    if condor != self.Invested_Condor:
                                                        continue
                                                    else:
                                                        self.Averaged_Down = True
                                                self.Trade_Counter += 1
                                                self.MarketOrder(condor.Put_Buy.Symbol, self.Amount_Of_Contracts, tag =f"{percentage_put_} Strike {condor.Put_Buy.Strike} pm {condor.Premium} Price {Price}")
                                                self.MarketOrder(condor.Put_Sell.Symbol, -self.Amount_Of_Contracts, tag =f"{percentage_put_} Strike {condor.Put_Sell.Strike} pm {condor.Premium} Price {Price}")
                                                self.MarketOrder(condor.Call_Buy.Symbol, self.Amount_Of_Contracts, tag =f"{percentage_call_} Strike {condor.Call_Buy.Strike} pm {condor.Premium} Price {Price}")
                                                self.MarketOrder(condor.Call_Sell.Symbol, -self.Amount_Of_Contracts, tag =f"{percentage_call_} Strike {condor.Call_Sell.Strike} pm {condor.Premium} Price {Price}")
                                                self.Avg_Down_Time = self.Time
                                                self.Put_Buy_Strike = condor.Put_Buy.Strike
                                                self.Put_Sell_Strike = condor.Put_Sell.Strike
                                                self.Call_Buy_Strike = condor.Call_Buy.Strike
                                                self.Call_Sell_Strike = condor.Call_Sell.Strike
                                                self.Invested_Condor = condor
                                                condor.Entry_Premium = condor.Premium
                                                condor.Margin_Required = ((condor.Put_Buy.Strike - condor.Put_Sell.Strike) * 100) * self.Amount_Of_Contracts
                                                self.Traded_Today = True
                                                self.Counter = self.Counter + 1
                                                self.Iron_Condor_Counter = self.Iron_Condor_Counter + 1
                                                
                                                self.Entered = True
                                                #self.Debug(f"{condor.open_call_range} {condor.open_put_range} ENTERED")
                                                if self.Allow_Re_enter:
                                                    self.Entered_With_PT = True
                                                #self.Debug(f"Range {self.Minimum_Distance} Avg {self.Current_Average} Current Open {self.Premium_At_Open}")
                    

                            #if not config.USE_VIX_ATR and not config.USE_VIX and not config.USE_ATR:
                                #self.Minimum_Distance = config.MINIMUM_DISTANCE
                                #self.Premium_Threshold = config.PREMIUM_THRESHOLD
                    # if condor.Lowest_Premium is None:
                    #     condor.Lowest_Premium = condor.Premium
                    
                    # if condor.Lowest_Premium > condor.Premium:
                    #     condor.Lowest_Premium = condor.Premium
                    
                    # put_3_min_distance_scanner = Price*0.01
                    # put_3_min_distance_scanner = math.floor(put_3_min_distance_scanner)

                  


                    # call_3_min_distance_scanner = Price*0.01
                    # call_3_min_distance_scanner = math.ceil(call_3_min_distance_scanner)

                    # if condor.Lowest_Premium * self.Premium_Multiplier <= condor.Premium:
                    #     if condor.Premium >= self.Premium_Threshold:
                    #         if not condor.Scanned_Already and condor_distance_put >= put_3_min_distance_scanner and condor_distance_call >= call_3_min_distance_scanner and (put_call_distance >= 0 or put_call_distance <= 2):
                    #             if self.Counter <= 20:
                    #                 percentage = ((abs(self.Securities[self.Spy].Price - condor.Put_Sell.Strike) / self.Securities[self.Spy].Price) + (abs(self.Securities[self.Spy].Price - condor.Call_Sell.Strike) / self.Securities[self.Spy].Price)) / 2
                    #                 percentage_call = abs((self.Securities[self.Spy].Price - condor.Call_Sell.Strike) / self.Securities[self.Spy].Price)

                    #                 percentage_put = abs((self.Securities[self.Spy].Price - condor.Put_Sell.Strike) / self.Securities[self.Spy].Price)


                    #                 percentage = round(percentage, 3)
                    #                 percentage_call = round(percentage_call, 3)
                    #                 percentage_put = round(percentage_put, 3)


                    #                 #if condor.Call_Buy.Strike - condor.Call_Sell.Strike >= 10:
                    #                 Breakeven_Price_Call = condor.Call_Sell.Strike + condor.Premium
                    #                 Breakeven_Price_Put = condor.Put_Sell.Strike - condor.Premium
                    #                 premium_increase = ((condor.Premium - condor.Lowest_Premium )/ condor.Lowest_Premium) * 100
                    #                 token_scanner = "5616527268:AAGkUitVosgYOntpLb_JU5HK_SSXm86GsVs"
                    #                 id_scanner = "-723291833"
                    #                 message_scanner = f"Premium has increased by %{premium_increase} \n Lowest Premium {condor.Lowest_Premium} \n Current Premium {condor.Premium} \n Percentage %{percentage} \n Sell {(condor.Put_Sell.Expiry).strftime('%b%d%-y')}   ${condor.Put_Sell.Strike}   Put \n Buy {(condor.Put_Buy.Expiry).strftime('%b%d%-y')}   ${condor.Put_Buy.Strike}   Put \n Buy {(condor.Call_Buy.Expiry).strftime('%b%d%-y') }   ${condor.Call_Buy.Strike}   Call \n Sell {(condor.Call_Sell.Expiry).strftime('%b%d%-y')}   ${condor.Call_Sell.Strike}   Call \n \n \n \n Price ${self.Securities[self.Spy].Price} \n  Premium {condor.Premium} \n Strike diff ${abs(condor.Put_Sell.Strike - condor.Put_Buy.Strike)} \n Breakeven Price Call {Breakeven_Price_Call} \n Breakeven Price Put {Breakeven_Price_Put} \n Call %{percentage_call} \n Put %{percentage_put} \n %{percentage} \n expiry {expiry_date}"
                    #                 condor.Scanned_Already = True
                    #                 self.Counter = self.Counter + 1
                    #                 self.Notify.Telegram(id=id_scanner, message=message_scanner, token=token_scanner)
                    #                 self.Debug(message_scanner)



    def Assign_Weighting(self, open_call_range, open_put_range, strike_diff):
        call_range_diff = open_call_range - config.RANGE_MAX
        put_range_diff = open_put_range - config.RANGE_MAX
        
        call_put_diff = abs(open_call_range - open_put_range)
        call_put_diff = math.ceil(call_put_diff)
        call_range_diff = round(call_range_diff, 3)
        put_range_diff = round(put_range_diff, 3)


        call_range_diff = (call_range_diff * 10) 
        put_range_diff = (put_range_diff * 10) 
        if call_put_diff != 0:
            range_weight = ((call_range_diff * config.RANGE_WEIGHT) + (put_range_diff * config.RANGE_WEIGHT)) / call_put_diff
        else:
            range_weight = ((call_range_diff * config.RANGE_WEIGHT) + (put_range_diff * config.RANGE_WEIGHT))
        #strike_weight = (config.STRIKE_MAX - strike_diff) * config.STRIKE_WEIGHT

        weight = range_weight #+ strike_weight

        return weight
                       
    


    def Generate_Key_To_Look_Up(self):
        open_price = self.Open_Price
        start= config.START
        increment = config.INCREMENT
        end = config.END
        current = start
        max_percent = config.MAX_PERCENT
        min_percent = config.MINIMUM_DISTANCE

        put_sell = (1 - min_percent) * open_price
        put_buy = (1 - min_percent) * open_price
        call_sell = (1 + min_percent) * open_price
        call_buy = (1 + min_percent) * open_price


        for i in count(0):
            put_buy += increment
            call_buy += increment
            current += increment
            string_add = f"{put_buy} {put_sell} {call_sell} {call_buy}"
            self.List_To_Look_Up.append(string_add)
            if current == end:
                put_sell += increment
                call_sell += increment
                put_buy = put_sell
                call_buy = call_sell
                current = start





    # def OnEndOfAlgorithm(self):
    #     self.Debug(max(self.List_Of_Len))
    #     self.Debug(min(self.List_Of_Len))

                            

    def UniverseFunc(self, universe):
    
        Price = self.Securities[self.Spy].Price
        ATM = self.Securities[self.Spy].Price * 0.06
        #self.Debug(self.Time)
        # OnlyApplyFilterAtMarketOpen()
        return universe.IncludeWeeklys().Strikes(-ATM, ATM).Expiration(TimeSpan.FromDays(0),TimeSpan.FromDays(0))
        


class Iron_Condor():


    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.Lowest_Premium = None
        self.Scanned_Already = 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.Weight = 0
    
    def Calculate_Premium(self, pb_premium, ps_premium, cb_premium, cs_premium):
        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
    


class Combinations():



    def __init__(self, algorithm, b, s):
        self.algorithm = algorithm

        self.S = s
        self.B = b