Overall Statistics
Total Trades
768
Average Win
0.62%
Average Loss
-0.37%
Compounding Annual Return
9.138%
Drawdown
5.700%
Expectancy
0.082
Net Profit
10.926%
Sharpe Ratio
0.724
Probabilistic Sharpe Ratio
32.993%
Loss Rate
60%
Win Rate
40%
Profit-Loss Ratio
1.68
Alpha
0.066
Beta
-0.065
Annual Standard Deviation
0.092
Annual Variance
0.009
Information Ratio
0.45
Tracking Error
0.19
Treynor Ratio
-1.024
Total Fees
$1311.50
Estimated Strategy Capacity
$1800000.00
Lowest Capacity Asset
SPY 31YMW3VCZ5TUU|SPY R735QTJ8XC9X
#region imports
from AlgorithmImports import *
#endregion
import math
class OptionTradeManagement:
    
    def __init__(self, algorithm, symbol_call, symbol_put):
        
        self.algorithm = algorithm
        
        self.symbol_call = symbol_call
        self.quantity_call = None
        
        self.entry_price_call = None
        self.stop_loss_call_ = None
        self.first_take_profit_call = None
        self.updated_first_take_profit_call = None
        self.second_take_profit_call = None
        self.third_take_profit_call = None
        self.fourth_take_profit_call = None
        self.fifth_take_profit_call = None
        self.sixth_take_profit_call = None
        self.seventh_take_profit_call = None
        
        self.trailing_call = False
        self.trailing_call_updated = False
        self.trailing_call_second = False
        self.trailing_call_third = False
        self.trailing_call_fourth = False
        self.trailing_call_fifth = False
        self.trailing_call_sixth = False
        self.trailing_call_seventh = False
        self.peak_price_call = None # for trailing purposes
        self.doubled_call = False
        self.doubled_put = False
        
        
        
        self.symbol_put = symbol_put
        self.quantity_put = None
        
        self.entry_price_put = None
        self.stop_loss_put = None
        self.first_take_profit_put = None
        self.updated_first_take_profit_put = None
        self.second_take_profit_put = None
        self.third_take_profit_put = None
        self.fourth_take_profit_put = None
        self.fifth_take_profit_put = None
        self.sixth_take_profit_put = None
        self.seventh_take_profit_put = None
        
        self.trailing_put = False
        self.trailing_put_updated = False
        self.trailing_put_second = False
        self.trailing_put_third = False
        self.trailing_put_fourth = False
        self.trailing_put_fifth = False
        self.trailing_put_sixth = False
        self.trailing_put_seventh = False
        self.peak_price_put = None # for trailing purposes
        
        
        
    def create_entry(self, size_call, size_put):
        
        self.quantity_call = size_call
        self.quantity_put = size_put
        
        self.algorithm.MarketOrder(self.symbol_call, size_call)
        self.algorithm.MarketOrder(self.symbol_put, size_put)
        
        self.entry_price_call = self.algorithm.Securities[self.symbol_call].AskPrice
        self.entry_price_put = self.algorithm.Securities[self.symbol_put].AskPrice
        
        self.first_take_profit_call = 10 * self.entry_price_call
        self.updated_first_take_profit_call = 10 * self.entry_price_call
        self.second_take_profit_call = 10 * self.entry_price_call 
        self.updated_first_take_profit_put = 10 * self.entry_price_put
        self.first_take_profit_put = 10 * self.entry_price_put
        self.second_take_profit_put = 10 * self.entry_price_put
        self.third_take_profit_call = 10 * self.entry_price_call
        self.third_take_profit_put = 10 * self.entry_price_put
        self.fourth_take_profit_put = 10 * self.entry_price_put
        self.fourth_take_profit_call = 10 * self.entry_price_call
        self.fifth_take_profit_put = 10 * self.entry_price_put
        self.fifth_take_profit_call = 10 * self.entry_price_call
        self.sixth_take_profit_put = 10 * self.entry_price_put
        self.sixth_take_profit_call = 10 * self.entry_price_call
        self.seventh_take_profit_call = 10 * self.entry_price_call
        self.seventh_take_profit_put = 10 * self.entry_price_put
        
        self.doubled_metric_call = 2 * self.entry_price_call
        self.doubled_metric_put = 2 * self.entry_price_put
        
        
        
        
        
        self.stop_loss_call = 0.25 * self.entry_price_call
        self.stop_loss_put = 0.25 * self.entry_price_put
        
        self.peak_price_call = self.entry_price_call
        self.peak_price_put = self.entry_price_put
        
        self.algorithm.Debug(f"{self.algorithm.Time} - Entering CALL: {self.symbol_call} @ entry: {self.entry_price_call} @ first_take_profit: {self.first_take_profit_call} @updated_take_profit:{self.updated_first_take_profit_call} @second_take_profit: {self.second_take_profit_call} @third_take_profit: {self.third_take_profit_call} @fourth_take_profit: {self.fourth_take_profit_call} @fifth_take_profit: {self.fifth_take_profit_call} @sixth_take_profit: {self.sixth_take_profit_call} @seventh_take_profit: {self.seventh_take_profit_call} stop_loss: {self.stop_loss_call}")
        self.algorithm.Debug(f"{self.algorithm.Time} - Entering PUT: {self.symbol_put} @ entry: {self.entry_price_put} @ first_take_profit: {self.first_take_profit_put} @updated_take_profit: {self.updated_first_take_profit_put} @second_take_profit: {self.second_take_profit_put} @third_take_profit: {self.third_take_profit_put} @fourth_take_profit: {self.fourth_take_profit_put} @fifth_take_profit: {self.fifth_take_profit_put} @sixth_take_profit: {self.sixth_take_profit_put} @seventh_take_profit: {self.seventh_take_profit_put} stop_loss: {self.stop_loss_put}")
        self.size = (self.entry_price_call * 100 * self.quantity_call) + (self.entry_price_put * 100 * self.quantity_put)
        self.algorithm.Debug("Total asset size: " + str(self.size))
        
        
        
    def doubled(self):
        
        
        call_price = self.algorithm.Securities[self.symbol_call].BidPrice
        put_price = self.algorithm.Securities[self.symbol_put].BidPrice
        
        if call_price >= self.doubled_metric_call:
            self.doubled_call = True
            
        
        if put_price >= self.doubled_metric_put:
            self.doubled_put = True
            
        
        if not self.doubled_call and not self.doubled_put:
            self.algorithm.Liquidate(self.symbol_call)
            self.algorithm.Liquidate(self.symbol_put)
            self.algorithm.Debug("Liquidating positions due to 7:30 PST rule")
                
            
            
            
        
            
        
        
        
    def check_and_update_position(self):
        
        
        call_price = self.algorithm.Securities[self.symbol_call].BidPrice
        put_price = self.algorithm.Securities[self.symbol_put].BidPrice
        
        ''' Update Peak Prices'''
        
        ## Updates Peak Incase we are trailing
        if call_price > self.peak_price_call:
            self.peak_price_call = call_price
        
        if put_price > self.peak_price_put:
            self.peak_price_put = put_price
        
        '''============== Check Take Profit and Start Trailing ==========='''
        # If we aren't trailing and we've hit our take profit
        # Start trailing and sell half
        if not self.trailing_call and call_price >= self.first_take_profit_call:
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.algorithm.Portfolio[self.symbol_call].Quantity == self.quantity_call:

                self.trailing_call = True
                sell_quantity = (self.quantity_call * .75 + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.first_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First 25% Profit Call {self.symbol_call} @ {call_price}")
            
        if not self.trailing_put and put_price >= self.first_take_profit_put:
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.algorithm.Portfolio[self.symbol_put].Quantity == self.quantity_put:
                self.trailing_put = True
                sell_quantity = (self.quantity_put * .75 + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.first_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First 25% Profit PUT {self.symbol_put} @ {put_price}")
        
        
        if not self.trailing_call_updated and call_price >= self.updated_first_take_profit_call:
            if self.algorithm.Portfolio[self.symbol_call].Invested:
                self.trailing_call_updated = True
                sell_quantity = (self.quantity_call * .75 + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.updated_first_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First Updated 100% Profit Call {self.symbol_call} @ {call_price}")
            
        if not self.trailing_put_updated and put_price >= self.updated_first_take_profit_put:
            
                self.trailing_put_updated = True
                sell_quantity = (self.quantity_put *.75 + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.updated_first_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First Updated 100% Profit Put {self.symbol_put} @ {put_price}")
             
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        if not self.trailing_call_second and call_price >= self.second_take_profit_call: 
            self.trailing_call_second = True
        
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.quantity_call // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.second_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit Call {self.symbol_call} @ {call_price}")
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
              
                sell_quantity = (self.quantity_call * .25 + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.second_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit Call {self.symbol_call} @ {call_price}")
            
        if not self.trailing_put_second and put_price >= self.second_take_profit_put:
            self.trailing_put_second = True
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.algorithm.Portfolio[self.symbol_put].Quantity == 1:
                sell_quantity = (self.quantity_put // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.second_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit PUT {self.symbol_put} @ {put_price}")
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.quantity_put * .25 + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.second_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit PUT {self.symbol_put} @ {put_price}")
                
        
        if not self.trailing_call_third and call_price >= self.third_take_profit_call:
            self.trailing_call_third = True
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.quantity_call // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.third_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit CALL {self.symbol_put} @ {call_price}")
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.third_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit CALL {self.symbol_put} @ {call_price}")
        
        if not self.trailing_put_third and put_price >= self.third_take_profit_put:
            self.trailing_put_third = True
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.third_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit PUT {self.symbol_put} @ {put_price}")
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.third_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit PUT {self.symbol_put} @ {put_price}")
        
        if not self.trailing_call_fourth and call_price >= self.fourth_take_profit_call:
            self.trailing_call_fourth = True 
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.algorithm.Portfolio[self.symbol_call].Quantity == 1:
                sell_quantity = (self.quantity_call // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.fourth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit CALL {self.symbol_call} @ {call_price}")
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.fourth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit CALL {self.symbol_put} @ {call_price}")
        
        
        if not self.trailing_put_fourth and put_price >= self.fourth_take_profit_put:
            self.trailing_put_fourth = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fourth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit PUT {self.symbol_put} @ {put_price}")
                
            
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fourth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit PUT {self.symbol_put} @ {put_price}")
                
                
                
    
        if not self.trailing_call_fifth and call_price >= self.fifth_take_profit_call:
            self.trailing_call_fifth = True 
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fifth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit Call {self.symbol_call} @ {call_price}")
                
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.fifth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit CALL {self.symbol_put} @ {call_price}")
        
        if not self.trailing_put_fifth and put_price >= self.fifth_take_profit_put:
            self.trailing_put_fifth = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fifth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit PUT {self.symbol_put} @ {put_price}")
                
                
            
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fifth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit PUT {self.symbol_put} @ {put_price}")
        
        
        
        
        
        if not self.trailing_call_sixth and call_price >= self.sixth_take_profit_call:
            self.trailing_call_sixth = True 
            
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.sixth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit Call {self.symbol_call} @ {call_price}")
                
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.sixth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit CALL {self.symbol_put} @ {call_price}")
        
        
        if not self.trailing_put_sixth and put_price >= self.sixth_take_profit_put:
            self.trailing_put_sixth = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.sixth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit PUT {self.symbol_put} @ {put_price}")
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.sixth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit PUT {self.symbol_put} @ {put_price}")
                
                
        
        if not self.trailing_call_seventh and call_price >= self.seventh_take_profit_call:
            self.trailing_call_seventh = True 
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.seventh_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit Call {self.symbol_call} @ {call_price}")
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.seventh_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit CALL {self.symbol_put} @ {call_price}")
                
        
        if not self.trailing_put_seventh and put_price >= self.seventh_take_profit_put:
            self.trailing_put_seventh = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.seventh_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit PUT {self.symbol_put} @ {put_price}")
        
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.seventh_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit PUT {self.symbol_put} @ {put_price}")
                
            
            
        
            
        '''=============== STOP LOSS ======================='''
        
        ### If we are trailing, Liquidate on stop loss hit
        if self.trailing_call:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
                
            
        
        ### If we are trailing, Liquidate on stop loss hit 
        if self.trailing_put:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
                
                
        
        
        
        
        if self.trailing_call_updated:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
               
        
        if self.trailing_put_updated:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
                
        
        
        
        
        if self.trailing_call_second:
            stop_dist = 10 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        if self.trailing_put_second:
            stop_dist = 10 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")          
    
     
     
     
     
     
     
     
     
     
        
        
        
        
        
        
        
        
        
        
        if self.trailing_call_third:
            stop_dist = .5 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        if self.trailing_put_third:
            stop_dist = .5 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_put_fourth:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_fourth:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        
        
        if self.trailing_put_fifth:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_fifth:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        
        if self.trailing_put_sixth:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_sixth:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        
        if self.trailing_put_seventh:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_seventh:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
            
            
    @property
    def is_active(self):
        return self.algorithm.Portfolio[self.symbol_call].Invested or \
            self.algorithm.Portfolio[self.symbol_put].Invested
    
    def liquid_limit(self):
        call_price = self.algorithm.Securities[self.symbol_call].BidPrice
        put_price = self.algorithm.Securities[self.symbol_put].BidPrice
        self.algorithm.Liquidate(self.symbol_call)
        self.algorithm.Liquidate(self.symbol_put)
        C_Price = call_price - .1
        
        if self.algorithm.Portfolio[self.symbol_call].Invested:
            self.algorithm.LimitOrder(self.symbol_call, -self.algorithm.Portfolio[self.symbol_call].Quantity, C_Price)
            self.algorithm.Debug("Call Limit price liquidation: " + str(C_Price))
           
           
        P_Price = put_price - .1
        
        if self.algorithm.Portfolio[self.symbol_put].Invested:
            self.algorithm.LimitOrder(self.symbol_put, -self.algorithm.Portfolio[self.symbol_put].Quantity, P_Price)
            self.algorithm.Debug("Put Limit price liquidation: " + str(P_Price))    
                
            
#region imports
from AlgorithmImports import *
#endregion
import math
class OptionTradeManagement2:
    
    def __init__(self, algorithm, symbol_call, symbol_put):
        
        self.algorithm = algorithm
        
        self.symbol_call = symbol_call
        self.quantity_call = None
        
        self.entry_price_call = None
        self.stop_loss_call_ = None
        self.first_take_profit_call = None
        self.updated_first_take_profit_call = None
        self.second_take_profit_call = None
        self.third_take_profit_call = None
        self.fourth_take_profit_call = None
        self.fifth_take_profit_call = None
        self.sixth_take_profit_call = None
        self.seventh_take_profit_call = None
        
        self.trailing_call = False
        self.trailing_call_updated = False
        self.trailing_call_second = False
        self.trailing_call_third = False
        self.trailing_call_fourth = False
        self.trailing_call_fifth = False
        self.trailing_call_sixth = False
        self.trailing_call_seventh = False
        self.peak_price_call = None # for trailing purposes
        
        
        self.doubled_call = False
        self.doubled_put = False
        
        
        
        self.symbol_put = symbol_put
        self.quantity_put = None
        
        self.entry_price_put = None
        self.stop_loss_put = None
        self.first_take_profit_put = None
        self.updated_first_take_profit_put = None
        self.second_take_profit_put = None
        self.third_take_profit_put = None
        self.fourth_take_profit_put = None
        self.fifth_take_profit_put = None
        self.sixth_take_profit_put = None
        self.seventh_take_profit_put = None
        
        self.trailing_put = False
        self.trailing_put_updated = False
        self.trailing_put_second = False
        self.trailing_put_third = False
        self.trailing_put_fourth = False
        self.trailing_put_fifth = False
        self.trailing_put_sixth = False
        self.trailing_put_seventh = False
        self.peak_price_put = None # for trailing purposes
        
        
    def create_entry(self, size_call, size_put):
        
        self.quantity_call = size_call
        self.quantity_put = size_put
        
        self.algorithm.MarketOrder(self.symbol_call, size_call)
        self.algorithm.MarketOrder(self.symbol_put, size_put)
        
        self.entry_price_call = self.algorithm.Securities[self.symbol_call].AskPrice
        self.entry_price_put = self.algorithm.Securities[self.symbol_put].AskPrice
        
        self.first_take_profit_call = 10 * self.entry_price_call
        self.updated_first_take_profit_call = 10 * self.entry_price_call
        self.second_take_profit_call = 10 * self.entry_price_call 
        self.updated_first_take_profit_put = 10 * self.entry_price_put
        self.first_take_profit_put = 10 * self.entry_price_put
        self.second_take_profit_put = 10 * self.entry_price_put
        self.third_take_profit_call = 10 * self.entry_price_call
        self.third_take_profit_put = 10 * self.entry_price_put
        self.fourth_take_profit_put = 10 * self.entry_price_put
        self.fourth_take_profit_call = 10 * self.entry_price_call
        self.fifth_take_profit_put = 10 * self.entry_price_put
        self.fifth_take_profit_call = 10 * self.entry_price_call
        self.sixth_take_profit_put = 10 * self.entry_price_put
        self.sixth_take_profit_call = 10 * self.entry_price_call
        self.seventh_take_profit_call = 10 * self.entry_price_call
        self.seventh_take_profit_put = 10 * self.entry_price_put
        self.doubled_metric_call = 2 * self.entry_price_call
        self.doubled_metric_put = 2 * self.entry_price_put
        
        
        
        
        
        self.stop_loss_call = 0.25 * self.entry_price_call
        self.stop_loss_put = 0.25 * self.entry_price_put
        
        self.peak_price_call = self.entry_price_call
        self.peak_price_put = self.entry_price_put
        
        self.algorithm.Debug(f"{self.algorithm.Time} - Entering CALL: {self.symbol_call} @ entry: {self.entry_price_call} @ first_take_profit: {self.first_take_profit_call} @updated_take_profit:{self.updated_first_take_profit_call} @second_take_profit: {self.second_take_profit_call} @third_take_profit: {self.third_take_profit_call} @fourth_take_profit: {self.fourth_take_profit_call} @fifth_take_profit: {self.fifth_take_profit_call} @sixth_take_profit: {self.sixth_take_profit_call} @seventh_take_profit: {self.seventh_take_profit_call} stop_loss: {self.stop_loss_call}")
        self.algorithm.Debug(f"{self.algorithm.Time} - Entering PUT: {self.symbol_put} @ entry: {self.entry_price_put} @ first_take_profit: {self.first_take_profit_put} @updated_take_profit: {self.updated_first_take_profit_put} @second_take_profit: {self.second_take_profit_put} @third_take_profit: {self.third_take_profit_put} @fourth_take_profit: {self.fourth_take_profit_put} @fifth_take_profit: {self.fifth_take_profit_put} @sixth_take_profit: {self.sixth_take_profit_put} @seventh_take_profit: {self.seventh_take_profit_put} stop_loss: {self.stop_loss_put}")
        self.size = (self.entry_price_call * 100 * self.quantity_call) + (self.entry_price_put * 100 * self.quantity_put)
        self.algorithm.Debug("Total asset size: " + str(self.size))
        
        
        
    def doubled(self):
        
        
        call_price = self.algorithm.Securities[self.symbol_call].BidPrice
        put_price = self.algorithm.Securities[self.symbol_put].BidPrice
        
        if call_price >= self.doubled_metric_call:
            self.doubled_call = True
            
        
        if put_price >= self.doubled_metric_put:
            self.doubled_put = True
            
        
        if not self.doubled_call and not self.doubled_put:
            self.algorithm.Liquidate(self.symbol_call)
            self.algorithm.Liquidate(self.symbol_put)
            self.algorithm.Debug("Liquidating positions due to 7:30 PST rule")   
        
        
        

        
    def check_and_update_position(self):
        
        
        call_price = self.algorithm.Securities[self.symbol_call].BidPrice
        put_price = self.algorithm.Securities[self.symbol_put].BidPrice
        
        ''' Update Peak Prices'''
        
        ## Updates Peak Incase we are trailing
        if call_price > self.peak_price_call:
            self.peak_price_call = call_price
        
        if put_price > self.peak_price_put:
            self.peak_price_put = put_price
        
        '''============== Check Take Profit and Start Trailing ==========='''
        # If we aren't trailing and we've hit our take profit
        # Start trailing and sell half
        if not self.trailing_call and call_price >= self.first_take_profit_call:
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.algorithm.Portfolio[self.symbol_call].Quantity == self.quantity_call:

                self.trailing_call = True
                sell_quantity = (self.quantity_call // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.first_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First 25% Profit Call {self.symbol_call} @ {call_price}")
            
        if not self.trailing_put and put_price >= self.first_take_profit_put:
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.algorithm.Portfolio[self.symbol_put].Quantity == self.quantity_put:
                self.trailing_put = True
                sell_quantity = (self.quantity_put // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.first_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First 25% Profit PUT {self.symbol_put} @ {put_price}")
        
        
        if not self.trailing_call_updated and call_price >= self.updated_first_take_profit_call:
            if self.algorithm.Portfolio[self.symbol_call].Invested:
                self.trailing_call_updated = True
                sell_quantity = (self.quantity_call * .5 + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.updated_first_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First Updated 100% Profit Call {self.symbol_call} @ {call_price}")
            
        if not self.trailing_put_updated and put_price >= self.updated_first_take_profit_put:
            
                self.trailing_put_updated = True
                sell_quantity = (self.quantity_put *.5 + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.updated_first_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking First Updated 100% Profit Put {self.symbol_put} @ {put_price}")
             
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        if not self.trailing_call_second and call_price >= self.second_take_profit_call: 
            self.trailing_call_second = True
        
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.quantity_call // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.second_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit Call {self.symbol_call} @ {call_price}")
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
              
                sell_quantity = (self.quantity_call * .25 + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.second_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit Call {self.symbol_call} @ {call_price}")
            
        if not self.trailing_put_second and put_price >= self.second_take_profit_put:
            self.trailing_put_second = True
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.algorithm.Portfolio[self.symbol_put].Quantity == 1:
                sell_quantity = (self.quantity_put // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.second_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit PUT {self.symbol_put} @ {put_price}")
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.quantity_put * .25 + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.second_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Second 100% Profit PUT {self.symbol_put} @ {put_price}")
                
        
        if not self.trailing_call_third and call_price >= self.third_take_profit_call:
            self.trailing_call_third = True
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.quantity_call // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.third_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit CALL {self.symbol_put} @ {call_price}")
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.third_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit CALL {self.symbol_put} @ {call_price}")
        
        if not self.trailing_put_third and put_price >= self.third_take_profit_put:
            self.trailing_put_third = True
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.third_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit PUT {self.symbol_put} @ {put_price}")
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.third_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Third Profit PUT {self.symbol_put} @ {put_price}")
        
        if not self.trailing_call_fourth and call_price >= self.fourth_take_profit_call:
            self.trailing_call_fourth = True 
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.algorithm.Portfolio[self.symbol_call].Quantity == 1:
                sell_quantity = (self.quantity_call // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.fourth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit CALL {self.symbol_call} @ {call_price}")
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.fourth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit CALL {self.symbol_put} @ {call_price}")
        
        
        if not self.trailing_put_fourth and put_price >= self.fourth_take_profit_put:
            self.trailing_put_fourth = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fourth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit PUT {self.symbol_put} @ {put_price}")
                
            
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fourth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fourth Profit PUT {self.symbol_put} @ {put_price}")
                
                
                
    
        if not self.trailing_call_fifth and call_price >= self.fifth_take_profit_call:
            self.trailing_call_fifth = True 
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fifth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit Call {self.symbol_call} @ {call_price}")
                
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.fifth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit CALL {self.symbol_put} @ {call_price}")
        
        if not self.trailing_put_fifth and put_price >= self.fifth_take_profit_put:
            self.trailing_put_fifth = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fifth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit PUT {self.symbol_put} @ {put_price}")
                
                
            
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.fifth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Fifth Profit PUT {self.symbol_put} @ {put_price}")
        
        
        
        
        
        if not self.trailing_call_sixth and call_price >= self.sixth_take_profit_call:
            self.trailing_call_sixth = True 
            
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.sixth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit Call {self.symbol_call} @ {call_price}")
                
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.sixth_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit CALL {self.symbol_put} @ {call_price}")
        
        
        if not self.trailing_put_sixth and put_price >= self.sixth_take_profit_put:
            self.trailing_put_sixth = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.sixth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit PUT {self.symbol_put} @ {put_price}")
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.sixth_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Sixth Profit PUT {self.symbol_put} @ {put_price}")
                
                
        
        if not self.trailing_call_seventh and call_price >= self.seventh_take_profit_call:
            self.trailing_call_seventh = True 
            if self.algorithm.Portfolio[self.symbol_call].Invested and self.quantity_call == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.seventh_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit Call {self.symbol_call} @ {call_price}")
            
            
            
            
            elif self.algorithm.Portfolio[self.symbol_call].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_call].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_call, -sell_quantity, self.seventh_take_profit_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit CALL {self.symbol_put} @ {call_price}")
                
        
        if not self.trailing_put_seventh and put_price >= self.seventh_take_profit_put:
            self.trailing_put_seventh = True 
            if self.algorithm.Portfolio[self.symbol_put].Invested and self.quantity_put == 1:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (2.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.seventh_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit PUT {self.symbol_put} @ {put_price}")
        
            
            elif self.algorithm.Portfolio[self.symbol_put].Invested:
                sell_quantity = (self.algorithm.Portfolio[self.symbol_put].Quantity // (4.0) + .5)
                self.algorithm.LimitOrder(self.symbol_put, -sell_quantity, self.seventh_take_profit_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Taking Seventh Profit PUT {self.symbol_put} @ {put_price}")
                
            
            
        
            
        '''=============== STOP LOSS ======================='''
        
        ### If we are trailing, Liquidate on stop loss hit
        if self.trailing_call:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
                
            
        
        ### If we are trailing, Liquidate on stop loss hit 
        if self.trailing_put:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
                
                
        
        
        
        
        if self.trailing_call_updated:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
               
        
        if self.trailing_put_updated:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
                
        
        
        
        
        if self.trailing_call_second:
            stop_dist = 10 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        if self.trailing_put_second:
            stop_dist = 10 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")          
    
     
     
     
     
     
     
     
     
     
        
        
        
        
        
        
        
        
        
        
        if self.trailing_call_third:
            stop_dist = .5 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        if self.trailing_put_third:
            stop_dist = .5 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_put_fourth:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_fourth:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        
        
        if self.trailing_put_fifth:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_fifth:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        
        if self.trailing_put_sixth:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_sixth:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
        
        if self.trailing_put_seventh:
            stop_dist = 3 * self.entry_price_put
            self.stop_loss_put = self.peak_price_put - stop_dist
            
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - Trail Stop PUT {self.symbol_put} @ {put_price} with stop: {self.stop_loss_put}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if put_price <= self.stop_loss_put and \
                            self.algorithm.Portfolio[self.symbol_put].Invested:
                self.algorithm.Liquidate(self.symbol_put)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop PUT {self.symbol_put} @ {put_price}  with stop: {self.stop_loss_put}")
        
        if self.trailing_call_seventh:
            stop_dist = 3 * self.entry_price_call
            self.stop_loss_call = self.peak_price_call - stop_dist
            
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - TRAIL Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
        else:
            # 50% stop loss - if hit, liquidate and if other leg not trailing
            ## update stop loss to entry
            if call_price <= self.stop_loss_call and \
                            self.algorithm.Portfolio[self.symbol_call].Invested:
                self.algorithm.Liquidate(self.symbol_call)
                self.algorithm.Debug(f"{self.algorithm.Time} - 50% Stop CALL {self.symbol_call} @ {call_price}  with stop: {self.stop_loss_call}")
                
            
            
    @property
    def is_active(self):
        return self.algorithm.Portfolio[self.symbol_call].Invested or \
            self.algorithm.Portfolio[self.symbol_put].Invested
    def liquid_limit(self):
        call_price = self.algorithm.Securities[self.symbol_call].BidPrice
        put_price = self.algorithm.Securities[self.symbol_put].BidPrice
        self.algorithm.Liquidate(self.symbol_call)
        self.algorithm.Liquidate(self.symbol_put)
        C_Price = call_price - .1
        
        if self.algorithm.Portfolio[self.symbol_call].Invested:
            self.algorithm.LimitOrder(self.symbol_call, -self.algorithm.Portfolio[self.symbol_call].Quantity, C_Price)
            self.algorithm.Debug("Call Limit price liquidation: " + str(C_Price))
           
           
        P_Price = put_price - .1
        
        if self.algorithm.Portfolio[self.symbol_put].Invested:
            self.algorithm.LimitOrder(self.symbol_put, -self.algorithm.Portfolio[self.symbol_put].Quantity, P_Price)
            self.algorithm.Debug("Put Limit price liquidation: " + str(P_Price))    
                
            
#region imports
from AlgorithmImports import *
#endregion
from TradeManagement import OptionTradeManagement
from TradeManagementNonOpex import OptionTradeManagement2
import math

'''
Add +-2 for QQQ 
'''

class OptionStrategy(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2021, 5, 2)  # Set Start Date
        self.SetEndDate(2022, 7, 8)  # Set End Date
        self.SetCash(100000)  # Set Strategy Cash
    
        self.ath = 422.17
        self.TotalUnrealizedProfit = 0
        
        
        self.position_dollar_size = 2000
        self.trade_managers = []
        
        self.symbol_call = None
        self.symbol_put = None
        
        self.opexDay = False
        
        self.tickers = ["SPY"]
        self.symbols = []
        self.allAth = {}
        self.allContracts = {}
        self.maxGap = 3
        
        for ticker in self.tickers:
            
            symbol = self.AddEquity(ticker, Resolution.Minute, extendedMarketHours=True)
            symbol.SetDataNormalizationMode(DataNormalizationMode.Raw)
            
            self.symbols.append(symbol.Symbol)
            
            history = self.History(symbol.Symbol, 1000, Resolution.Daily)
            high = -1
            for tuple in history.itertuples():
                if tuple.close > high:
                    high = tuple.high
            self.allAth[symbol.Symbol] = high
        
        for symbol in self.symbols:
            self.allContracts[symbol] = []

        # To initialize options data as needed - needed for options
        self.SetSecurityInitializer(lambda security : security.SetMarketPrice(self.GetLastKnownPrice(security)))
        
        # DAILY MWF ENTRY
        # for live trading 1 min after market open should work
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                self.TimeRules.AfterMarketOpen("SPY", 2), self.AtMarketOpen)
                
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday),
                self.TimeRules.AfterMarketOpen("SPY", 0), self.Opex)
                
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Tuesday, DayOfWeek.Thursday),
                self.TimeRules.AfterMarketOpen("SPY", 0), self.NonOpex)
                
        #self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday),
        #         self.TimeRules.AfterMarketOpen("SPY", 1), self.grabOpen)
                
        self.Schedule.On(self.DateRules.EveryDay("SPY"), 
                self.TimeRules.AfterMarketOpen("SPY", .1), self.Outright_exit_loss)
        
        self.Schedule.On(self.DateRules.EveryDay("SPY"), 
                self.TimeRules.AfterMarketOpen("SPY", .1), self.UpdateATH)
        
        # EXIT
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.At(15, 57), self.BeforeMarketClose)
        
        # liquidate if 7:30 and leg hasn't doubled
        
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.At(10, 30), self.leg_double)
       
        #self.Schedule.On(self.DateRules.EveryDay("QQQ"), self.TimeRules.At(9, 30), self.TakeProfits)
        
    # def grabOpen(self):
    #     self.spyOpening = self.Securities[self.spy].Open
    
    def Opex(self):
        self.opexDay = True
        
    def NonOpex(self):
        self.opexDay = False
    
    def AtMarketOpen(self):
        
        for symbol in self.symbols:
            ''' When switched also comment this line out '''
            self.opening = self.Securities[symbol].Open
            self.Debug(self.opening)
            history = self.History(symbol, 1, Resolution.Daily)
            try:
                yesterdayClose = math.floor(float(history.loc[symbol]["close"]))
            except:
                try:
                    history = self.History(symbol, 2, Resolution.Daily)
                    yesterdayClose = math.floor(float(history.loc[symbol]["close"][-1]))
                except:
                    
                    self.Debug("Failed : " + str(symbol))
                    return
            gapSpread = abs(self.opening - yesterdayClose)
            self.Debug(str(symbol.Value) + " GAP " + str(gapSpread))
            #if gapSpread >= self.maxGap:
                #self.Log(f'Market GAPPED...not running')
                #continue
            
            open_price = math.floor(self.opening)
            if self.opening == -1:
                continue
            
            spread = abs(((math.floor(self.allAth[symbol])) - open_price))
            self.Debug(str(symbol.Value) + " OPEN: " + str(open_price) + " ATH SPREAD: " + str(spread) + " " + str(self.Time))
            if spread <= 3:
                self.Log(f'Market is at ATH...not running')
                continue
            
            call_symbol, put_symbol = self.select_contracts(symbol, self.opening)
            if not call_symbol or not put_symbol:
                self.Log(f'Return AtMarketOpen because one of the symbols is None. call_symbol is {call_symbol} and put_symbol is {put_symbol}.')
                continue
            
            call_margin = self.position_dollar_size // 2
            put_margin = self.position_dollar_size // 2
            
            self.Debug("Call Margin: " + str(call_margin))
            self.Debug("Put Margin: " + str(put_margin))
            
            # Quick fix for div by zero error
            if float(self.Securities[call_symbol].BidPrice == 0.0) or (self.Securities[put_symbol].AskPrice) == 0.0:
                self.Debug("Div error occured on " + str(self.Time))
                return
            
            call_size = self.calculate_leg_size(call_symbol, call_margin, "Call")
            put_size = self.calculate_leg_size(put_symbol, put_margin, "Put")
            
            # self.Debug("Call Size: " + str(call_size))
            # self.Debug("Put Size: " + str(put_size))
                    
            self.symbol_call = call_symbol
            self.symbol_put = put_symbol
            
            if self.opexDay == True:
                self.Log(f'Running OPEX Exits')
                trade_manager = OptionTradeManagement(self, call_symbol, put_symbol)
            elif self.opexDay == False:
                self.Log(f'Running NON OPEX Exits -- Not running')
                #continue 
                trade_manager = OptionTradeManagement2(self, call_symbol, put_symbol)
            
            trade_manager.create_entry(call_size, put_size)
            
            self.trade_managers.append(trade_manager)
            morning_balance = (self.Portfolio.TotalPortfolioValue)
            self.Debug(morning_balance)
            
            self.allContracts[symbol].append(call_symbol)
            self.allContracts[symbol].append(put_symbol)
    
    def BeforeMarketClose(self):
        
    
        self.Debug(f"1:10 PST/4:10 EST Liquidate")
        
        for trade_manager in self.trade_managers:
            
            if not trade_manager.is_active:
                trade_manager = None # get rid of it
                continue
            
            
            trade_manager.liquid_limit()
            
            
            
    def leg_double(self):
        
    
        for trade_manager in self.trade_managers:
            
            if not trade_manager.is_active:
                trade_manager = None # get rid of it
                continue
            
            trade_manager.doubled()
               
                
                
        
            
        
    def OnData(self, data):
        
        
    
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
            Arguments:
                data: Slice object keyed by symbol containing the stock data
        '''

        for trade_manager in self.trade_managers:
            
            if not trade_manager.is_active:
                trade_manager = None # get rid of it
                continue
            
            trade_manager.check_and_update_position()
            
    
    def calculate_leg_size(self, contract_symbol, call_margin, contract_type):
        
        x = self.Securities[contract_symbol].AskPrice
        y = self.Securities[contract_symbol].BidPrice
        contract_price = x + y
        self.Debug("x or ask : " + str(x))
        self.Debug("y or bid: " + str(y))
        self.Debug("x + y or bid + ask : " + str(contract_price))
        # (self.Securities[contract_symbol].AskPrice + self.Securities[contract_symbol].BidPrice) // 2
        temp_price = contract_price * (.5)
        self.Debug(" temp price or actual con price used in algo calculation: " + str(temp_price))
        if temp_price == 0:
            contract_price = contract_price * (.5)
        else:
            contract_price = temp_price
            
        self.Debug("ASKKKK " + str(self.Securities[contract_symbol].AskPrice))
        self.Debug("BIDDDD " + str(self.Securities[contract_symbol].BidPrice))
        
       
        contract_premium = temp_price * 100.0
        self.Debug("Here are the actual contract prices: ")
        self.Debug(f"{contract_symbol} : {temp_price}")
      
        #if contract_premium > 250:
           # contract_premium = 100000
        
       
        
        self.Debug("Leg Margin " + str(call_margin))
        # self.Debug("Prem " + str(contract_premium))
        # self.Debug(str(call_margin) + " Prem" + str(contract_premium))
        total_contracts = call_margin // contract_premium
        
        total_contracts_divisible_by_two = math.ceil(total_contracts)
        
        total_leg_cost = (total_contracts_divisible_by_two * contract_premium)
        
        #if total_leg_cost > 5000:
            #self.Debug("LEG COST GREATER THAN 5000 " + str(total_leg_cost))
            #total_contracts_divisible_by_two = total_contracts_divisible_by_two - 5

        self.Debug("Type: " + str(contract_type) + ". # of contracts: " + str(total_contracts_divisible_by_two) + ". Price: " + str(contract_price) + ". Premium: " + str(contract_premium) + ". Estimated Total leg cost: " + str(total_leg_cost))
        
        return total_contracts_divisible_by_two
        
    def select_option(self, contract_symbols, right, strike, expiry):
        '''Picks out contract given parameters'''
        # filter by right
        filtered_by_right = [c for c in contract_symbols if c.ID.OptionRight == right]
        if not filtered_by_right:
            self.Log(f'No symbol with right: {right}')
            return None
        
        # lambda # - anonymous
        sorted_expiry = sorted(contract_symbols, key=lambda c : abs(c.ID.Date - expiry))
        closest_expiry_to_desired_expiry = sorted_expiry[0].ID.Date
        
        all_contracts_with_closest_expiry = [c for c in filtered_by_right if c.ID.Date == closest_expiry_to_desired_expiry]
        if not all_contracts_with_closest_expiry:
            self.Log(f'No symbol with expity: {closest_expiry_to_desired_expiry}')
            return None
        
        ''' Selects option '''
        sorted_by_strike = sorted(all_contracts_with_closest_expiry,
                                key=lambda c : abs(c.ID.StrikePrice - strike), reverse = False)
        
        if not sorted_by_strike:
            self.Log(f'No symbol found for given arguments: {right} {strike} {expiry}')
            return None

        selected_contract = sorted_by_strike[0]
        self.AddOptionContract(selected_contract, Resolution.Minute)
        self.Debug("Contract Strike Price: " + str(selected_contract.ID.StrikePrice))
        return selected_contract
            
    def select_contracts(self, symbol, opening):
        # Alex: I moved GetOptionContractList outside select_option so we call it just one
        # then we pass the results to select_option to filter
        # list of symbols (tickers) for each available contract
        contract_symbols = self.OptionChainProvider.GetOptionContractList(symbol, self.Time)
        if not contract_symbols:
            self.Log(f'GetOptionContractList returned an empty list on {self.Time}')
            return None, None

        open_price = math.floor(opening)

        put_strike = open_price - 1
        put_expiry = self.Time
        
        call_strike = open_price + 1
        call_expiry = self.Time

        countCall = len([x for x in contract_symbols if x.ID.OptionRight == OptionRight.Call])
        countPut = len([x for x in contract_symbols if x.ID.OptionRight == OptionRight.Put])
        self.Debug(f"SPY open price: {open_price}. Available contracts: {len(contract_symbols)} Call: {countCall} Put: {countPut}")

        selected_call_symbol = self.select_option(contract_symbols, OptionRight.Call, call_strike, call_expiry)
        selected_put_symbol = self.select_option(contract_symbols, OptionRight.Put, put_strike, put_expiry)            
        
        return selected_call_symbol, selected_put_symbol
        
    #def BeforeMarketClose(self): 
        #self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday),
                #self.TimeRules.BeforeMarketClose("QQQ", 1), self.BeforeMarketClose)
        #self.Liquidate()
    
    def Outright_exit_loss(self):
        sold = []
        for symbol, contracts in self.allContracts.items():
            if len(contracts) < 1:
                continue
            if contracts[0] == None or contracts[1] == None:
                continue
            if (self.Portfolio[contracts[0]].UnrealizedProfitPercent + self.Portfolio[contracts[1]].UnrealizedProfitPercent) >=.25:
                self.Liquidate()
                self.Debug("target hit")
                sold.append(symbol)
                
        for symbol in sold:
            self.allContracts[symbol] = []
        
        
        # if self.symbol_put == None or self.symbol_call == None:
        #     return
        
        # trading_size = self.position_dollar_size
        # if self.TotalUnrealizedProfit // trading_size >= abs(.1):
        #     if self.Portfolio[self.symbol_call].Quantity == self.quantity_call and self.Portfolio[self.symbol_put].Quantity == self.quantity_put:
        #         self.Liquidate()
        #         self.Debug("outright loss hit")
                
            
        
       # portfolio_profit = self.Securities[self.symbol_call].Holdings.UnrealizedProfitPercent + self.Securities[self.symbol_call].Holdings.UnrealizedProfitPercent
        ''' It might be better to use the self.Portfolio object for profit percent on the portfolio rather than self.Securities, due to position weighting '''
        #portfolio_profit = self.Portfolio.TotalUnrealizedProfit
        #self.Debug("PORT " + str(portfolio_profit))
        
        #if portfolio_profit == -.10:
            #if self.Portfolio[self.symbol_call].Quantity == self.quantity_call and self.Portfolio[self.symbol_put].Quantity == self.quantity_put:
                #self.Liquidate()
                #self.Debug("outright loss hit")
                
    def UpdateATH(self): 
        for symbol in self.symbols:
            high = self.Securities[symbol].High
            self.Debug(str(symbol.Value) + " HIGH: " + str(high) + ". ATH: " + str(self.allAth[symbol]))
        
            if high > self.allAth[symbol]:
                self.allAth[symbol] = high
    #def TakeProfits(self):
        #self.Total_Port_Value = self.Portofolio.TotalPortfolioValue