Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
4.457
Tracking Error
0.124
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
from AlgorithmImports import *
from metrics.simple_price_metrics.Price import *
from metrics.simple_price_metrics.DMA import *
from metrics.simple_price_metrics.OnePercentValue import *
from metrics.simple_price_metrics.DayHigh import *
from metrics.simple_price_metrics.DayLow import *

from metrics.price_change_metrics.PercentageUpDownFromOpen import *
from metrics.price_change_metrics.Last52WeekHighPercentage import *
from metrics.price_change_metrics.MarketOpenChangeDMAPercentage import *
from metrics.price_change_metrics.DayChangePercentage import *
from metrics.price_change_metrics.DMAGapUpDown import *

from metrics.volume_metrics.VWAP import *
from metrics.volume_metrics.PercentageOfMarketPriceVsVWAP import *
from metrics.volume_metrics.VolumeDMA import *
from metrics.volume_metrics.PercentageAboveDailyVolume import *
from metrics.volume_metrics.VolumePerTimeMultipleVs30DMA import *
from metrics.volume_metrics.VolumeChangePercentage import *
from metrics.volume_metrics.NetVolumePercentage import *
from metrics.volume_metrics.FiftenSeconds30DMAVolume import *

from metrics.day_range_metrics.DayFactorPrice import *
from metrics.day_range_metrics.DayPriceRangePercentage import *
from metrics.day_range_metrics.MarketOpenRangeDMAPercentage import *
from metrics.day_range_metrics.PricePercentageOf30DayRange import *
from metrics.day_range_metrics.PricePercentageOf52WeekRange import *
from metrics.day_range_metrics.PricePercentageOfDayRange import *
from metrics.day_range_metrics.RangePercentageDMA import *
from metrics.day_range_metrics.RangeMultiple import *
from metrics.day_range_metrics.RangeMultiple7DMA import *
from metrics.day_range_metrics.DayPercentageChangeOfDMARangePercentage import *

from trades.tradecollections.TradeOne import TradeOne
from trades.tradecollections.TradeThree import TradeThree
from trades.tradecollections.TradeTwo import TradeTwo


class Config:

    def __init__(self):
        self.set_symbols()
        self.set_plot_metrics()
        self.set_metrics()
        self.set_trades()

    def set_symbols(self):
        self.symbols = ['AAP', 'AAPL', 'ABBV', 'ABCL', 'ABNB', 'ABSI', 'ACAH', 'ACM', 'ACN', 'ADBE', 'ADI', 'ADMP', 'ADSK', 'AER', 'AFRM', 'AGCB', 'AGI', 'AI', 'ALCC', 'ALGN', 'ALIT', 'ALNY', 'AMAT', 'AMD', 'AMZN', 'ANAC', 'AON', 'APA', 'APG', 'APO', 'APSG', 'AR', 'ARKK', 'ARMK', 'ARNC', 'ASML', 'ASPU', 'ATIP', 'ATUS', 'ATVI', 'AUR', 'AUS', 'AVPT', 'AXP', 'AXTA', 'BABA', 'BAC', 'BBDC', 'BBWI', 'BEC']
    
    
    def set_metrics(self):
        # please note that the order matters so if metrics x depends on
        # metrics y you need to add metrics x before metrics y
        self.metrics={
            "real_time"  : [ ("Price",Price),("VWAP",VWAP),("OnePercentValue",OnePercentValue),("PercentageOfMarketPriceVsVWAP",PercentageOfMarketPriceVsVWAP),
                             ("DayHigh", DayHigh), ("DayLow", DayLow)],
        
            "weekly"     : [ ("PricePercentageOf52WeekRange",PricePercentageOf52WeekRange)],
                            
            "daily"      : [ ("1DayChangePercentage",DayChangePercentage,[1]),("7DayChangePercentage",DayChangePercentage,[7]),("30DayChangePercentage",DayChangePercentage,[30]),
                             ("7DMAGapUpDown",DMAGapUpDown,[7]),("30DMAGapUpDown",DMAGapUpDown,[30]),
                             ("MarketOpenChange7DMAPercentage",MarketOpenChangeDMAPercentage,[7]),("MarketOpenChange30DMAPercentage",MarketOpenChangeDMAPercentage,[30]),
                             ("PercentageUpDownFromOpen",PercentageUpDownFromOpen),
                             ("DayNetVolumePercentage",NetVolumePercentage,[1]),("WeekNetVolumePercentage",NetVolumePercentage,[7]),("MonthNetVolumePercentage",NetVolumePercentage,[30]),
                             ("Volume7DMA",VolumeDMA,[7]),("Volume30DMA",VolumeDMA,[30]),
                             ("DayLowerQuadrantPrice",DayFactorPrice,[0.25]),("DayMiddlePrice",DayFactorPrice,[0.5]),("DayUpperQuadrantPrice",DayFactorPrice,[0.75]),
                             ("DayPriceRangePercentage",DayPriceRangePercentage),
                             ("PricePercentageOfDayRange",PricePercentageOfDayRange),
                             ("RangePercentage7DMA",RangePercentageDMA,[7]),("RangePercentage30DMA",RangePercentageDMA,[30]),
                             ("HistoricalRangePercentage7DMA",RangePercentageDMA,[7,7]),("HistoricalRangePercentage30DMA",RangePercentageDMA,[30,30]),
                             ("DayPercentageChangeOf7DMARangePercentage",DayPercentageChangeOfDMARangePercentage,[7]),("DayPercentageChangeOf30DMARangePercentage",DayPercentageChangeOfDMARangePercentage,[30]),
                             ("PricePercentageOf30DayRange",PricePercentageOf30DayRange),
                             ("RangeMultiple",RangeMultiple),("RangeMultiple7DMA",RangeMultiple7DMA),
                             ("DMA50",DMA,[50]),("DMA100",DMA,[100])
                            ],
           
            "minute"     : [ ("DayVolumeChangePercentage",VolumeChangePercentage,[1]),("WeekVolumeChangePercentage",VolumeChangePercentage,[7]),("MonthVolumeChangePercentage",VolumeChangePercentage,[30]),
                             ("VolumePerTimeMultipleVs30DMA",VolumePerTimeMultipleVs30DMA),
                             ("PercentageAboveDailyVolume",PercentageAboveDailyVolume)
                           ],
            
            "15_seconds" : [("Last52WeekHighPercentage",Last52WeekHighPercentage),("FiftenSeconds30DMAVolume",FiftenSeconds30DMAVolume)],
            
            "15_minute_after_market_open":[("MarketOpenRange7DMAPercentage",MarketOpenRangeDMAPercentage,[7]),("MarketOpenRange30DMAPercentage",MarketOpenRangeDMAPercentage,[30])]
        
        }
        
    def set_trades(self):
        self.trades = [TradeOne,TradeTwo] 
    

    @classmethod
    def set_parameters(cls):
        cls.parameters={
            "PauseAlgo"           : True,
            "C1"                  : True,
            "C2"                  : True,
            "C3"                  : True,
            "C4"                  : True,
            "C5"                  : True,
            "Trading Algorithm"   : True,
            "SameConditionTimeC1" : 0, 
            "SameConditionTimeC2" : 1, 
            "SameConditionTimeC3" : 30, 
            "SameConditionTimeC4" : 10, 
            "SameConditionTimeC5" : 10,
            "Parameter 1"         : 135,
            "Parameter 2"         : 145,
            "Parameter 3"         : 300,
            "Parameter 4"         : 7,
            "Parameter 5"         : 0.85,
            "VWAP_PCT"            : 40,
            "Rally_X_Min_PCT"     : 8,
            "Rally_X_Max_PCT"     : 20,
            "Rally_Y_PCT"         : 4,
            "OffsetPCT"           : 0.1,
            "SharesToSell"        : 100,
            "StopLoss"            : 200,
            "ProfitTakeC1"        : 15,
            "ProfitTakeC2"        : 15,
            "ProfitTakeC3"        : 10,
            "ProfitTakeC4"        : 15,
            "ProfitTakeC5"        : 15,
            
        }
        return cls.parameters


    def set_plot_metrics(self):
        self.plot_metrics=["VWAP"]
from AlgorithmImports import *
from symbols.symbol import *
from datetime import timedelta
from config import Config

class App(QCAlgorithm):

    symbols = {}

    def Initialize(self):
        self.SetStartDate(2023, 2, 8)  # Set Start Date
        self.SetCash(100000)           # Set Strategy Cash
        self.config: Config = Config()

        # map for the disired history data of the application
        self.WeekHistory = {}
        self.DayHistory = {}
        self.MinuteHistory = {}
        self.SecondHistory = {}

        # create symbols
        for name in self.config.symbols:
            sp = Symbol(self, name)
            self.symbols[name] = sp

            self.AddEquity(name, Resolution.Second)
            self.symbols[name].addMetric()
            self.symbols[name].addTrades()

            # please add the desired rolling window with the max bars you need
            self.WeekHistory[name] = RollingWindow[TradeBar](52)
            self.Consolidate(name, CalendarType.Weekly, self.WeekHistoryHandler)

            self.DayHistory[name] = RollingWindow[TradeBar](60)
            self.Consolidate(name, Resolution.Daily, self.DayHistoryHandler)

            self.MinuteHistory[name] = RollingWindow[TradeBar](24000)  # 60 days
            self.Consolidate(name, Resolution.Minute, self.MinuteHistoryHandler)

            self.SecondHistory[name] = RollingWindow[TradeBar](15)

        # this schedule assumes every symbol trade on the same exchange
        self.Schedule.On(self.DateRules.EveryDay(self.config.symbols[0]),
                         self.TimeRules.AfterMarketOpen(self.config.symbols[0], 16),
                         self.MarketOpenUpdate)
        self.Schedule.On(self.DateRules.EveryDay(self.config.symbols[0]),
                         self.TimeRules.Every(timedelta(seconds=15)),
                         self.FiftenSecondUpdate)

        self.SetWarmUp(TimeSpan.FromDays(380), Resolution.Minute)

    def OnData(self, data: Slice):
        if self.IsWarmingUp:
            return

        for symbol, bar in data.Bars.items():            
            if symbol.Value not in self.SecondHistory:
                continue
            self.SecondHistory[symbol.Value].Add(bar)

            if self.SecondHistory[symbol.Value].IsReady:
                self.symbols[symbol.Value].update("real_time")

            self.symbols[symbol.Value].update_trade()
            self.symbols[symbol.Value].trade()

    def OnOrderEvent(self, orderEvent: OrderEvent) -> None:
        self.symbols[orderEvent.Symbol.Value].handle_order_event(orderEvent)
    
    def WeekHistoryHandler(self, bar):
        if bar is None or bar.Symbol is None or bar.Symbol.Value not in self.WeekHistory:
            return
        self.WeekHistory[bar.Symbol.Value].Add(bar)
        if not self.WeekHistory[bar.Symbol.Value].IsReady:
            return

        self.symbols[bar.Symbol.Value].update("weekly")

    def DayHistoryHandler(self, bar):
        if bar is None or bar.Symbol is None or bar.Symbol.Value not in self.DayHistory:
            return
        self.DayHistory[bar.Symbol.Value].Add(bar)
        if not self.DayHistory[bar.Symbol.Value].IsReady:
            return

        self.symbols[bar.Symbol.Value].update("daily")

    def MinuteHistoryHandler(self, bar):
        if bar is None or bar.Symbol is None or bar.Symbol.Value not in self.MinuteHistory:
            return
        self.MinuteHistory[bar.Symbol.Value].Add(bar)
        if self.IsWarmingUp:
            return

        self.symbols[bar.Symbol.Value].update("minute")

    def FiftenSecondUpdate(self):
        if self.IsWarmingUp:
            return
        for symbol in self.symbols.keys():
            if self.SecondHistory[symbol].IsReady:
                self.symbols[symbol].update("15_seconds")

    def MarketOpenUpdate(self):
        for symbol in self.symbols.keys():
            if self.MinuteHistory[symbol].IsReady:
                self.symbols[symbol].update("15_minute_after_market_open")
# region imports
from AlgorithmImports import *
# endregion
from abc import ABC, abstractmethod

class Metric(ABC):

    @abstractmethod
    def calculate(self):
        pass
# __init__.py
from AlgorithmImports import *
from metrics.Metric import Metric

class DayFactorPrice(Metric):

    """
    18) Day’s Lower ¼ Price 
    The price of the lower quadrant of the day range. 

    19) Day’s Middle Price 
    The MidDay Range Price

    20) Day’s Upper ¼ Price 
    The upper quadrant price of the day range. 

    """

    def __init__(self, algo, name, factor):
        self.name = name
        self.algorithm = algo
        self.factor = factor
        self.IsReady = False

    def calculate(self):
        high = self.algorithm.DayHistory[self.name][0].High
        low = self.algorithm.DayHistory[self.name][0].Low
        self.Value = self.factor * (high - low) + low
        self.IsReady = True
from metrics.Metric import Metric
from AlgorithmImports import *
from .RangePercentageDMA import *

class DayPercentageChangeOfDMARangePercentage(Metric):

    """
    16) 7 Day Percentage Change of 7 DMA Range Percentage
    The percentage change of the last day’s 7 DMA Range Vs the 7th historical day 7 DMA Range

    17) 30 Day Percentage Change of 30 DMA Range Percentage
    The percentage change of the last day’s 30 DMA Range Vs the 30th historical day 30 DMA Range

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        if not self.algorithm.symbols[self.name].metrics["RangePercentage"+str(self.length)+"DMA"].IsReady:
            return
        if not self.algorithm.symbols[self.name].metrics["HistoricalRangePercentage"+str(self.length)+"DMA"].IsReady:
            return

        dma = self.algorithm.symbols[self.name].metrics["RangePercentage"+str(self.length)+"DMA"].Value

        historical_dma = self.algorithm.symbols[self.name].metrics["HistoricalRangePercentage"+str(self.length)+"DMA"].Value

        self.Value = (dma - historical_dma) * 100 / dma
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class DayPriceRangePercentage(Metric):

    """
    3) Day’s Price Range Percentage 
    (Day High - Day Low) * 100 / Day Open 

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        high = self.algorithm.DayHistory[self.name][0].High
        low = self.algorithm.DayHistory[self.name][0].Low
        open = self.algorithm.DayHistory[self.name][0].Open
        self.Value = (high - low) * 100 / open
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric
from statistics import mean
from datetime import time

class MarketOpenRangeDMAPercentage(Metric):

    """
    21) Market Open Range 7 DMA Percentage 
    The 7 DMA of Daily Range.

    22) Market Open Range 30 DMA Percentage 
    The 30 DMA of Daily Range.

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        day_range = []
        for i in range(390 * self.length):
            if self.algorithm.MinuteHistory[self.name][i].EndTime.time() == time(hour=9, minute=45):
                self.high = self.algorithm.MinuteHistory[self.name][i].High
                self.low = self.algorithm.MinuteHistory[self.name][i].Low

            if self.algorithm.MinuteHistory[self.name][i].EndTime.time() < time(hour=9, minute=45):
                self.high = max(self.high, self.algorithm.MinuteHistory[self.name][i].High)
                self.low = min(self.low, self.algorithm.MinuteHistory[self.name][i].Low)

            if self.algorithm.MinuteHistory[self.name][i].EndTime.time() == time(hour=9, minute=31):
                open = self.algorithm.MinuteHistory[self.name][i].Open
                day_range.append((self.high - self.low) * 100 / open)

        self.Value = mean(day_range)
        self.IsReady = True
from metrics.Metric import Metric
from AlgorithmImports import *

class PricePercentageOf30DayRange(Metric):

    """
    12) Price Percentage of 30 Day Range 
    The last price percentage of the the last 30 Days Price Range

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        high = max([bar.High for bar in list(self.algorithm.DayHistory[self.name])[:30]])
        low = min([bar.Low for bar in list(self.algorithm.DayHistory[self.name])[:30]])
        close = self.algorithm.DayHistory[self.name][0].Close

        self.Value = (close - low) * 100 / (high - low)
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric


class PricePercentageOf52WeekRange(Metric):

    """
    13) Price Percentage of 52 Week Range
    The last price percentage of the the last 52 Weeks Price Range

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        high = max([bar.High for bar in list(self.algorithm.WeekHistory[self.name])[:52]])
        low = min([bar.Low for bar in list(self.algorithm.WeekHistory[self.name])[:52]])
        close = self.algorithm.WeekHistory[self.name][0].Close

        self.Value = (close - low) * 100 / (high - low)
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class PricePercentageOfDayRange(Metric):

    """
    2) Price Percentage of Day Range 
    The last price percentage of the day range. 
    (Day Close - Day Low) * 100 / (Day High - Day Low)

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        high = self.algorithm.DayHistory[self.name][0].High
        low = self.algorithm.DayHistory[self.name][0].Low
        close = self.algorithm.DayHistory[self.name][0].Close
        
        if high - low == 0:
            return

        self.Value = (close - low) * 100 / (high - low)
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric


class RangeMultiple(Metric):

    """
    6) Range Multiple 
    Day’s Price Range Percentage / 30 DMA Range Percentage

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        if not self.algorithm.symbols[self.name].metrics['DayPriceRangePercentage'].IsReady:
            return
        if not self.algorithm.symbols[self.name].metrics['RangePercentage30DMA'].IsReady:
            return

        self.Value = self.algorithm.symbols[self.name].metrics['DayPriceRangePercentage'].Value /\
            self.algorithm.symbols[self.name].metrics['RangePercentage30DMA'].Value
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric
from collections import deque
from statistics import mean

class RangeMultiple7DMA(Metric):

    """
    7) 7 DMA Range Multiple 
    The 7 Day Simple Moving Average of the Range Multiple

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.Values = RollingWindow[float](7)
        self.IsReady = False

    def calculate(self):
        if not self.algorithm.symbols[self.name].metrics['RangeMultiple'].IsReady:
            return

        self.Values.Add(self.algorithm.symbols[self.name].metrics['RangeMultiple'].Value)

        if not self.Values.IsReady:
            return
        self.Value = mean(list(self.Values))
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric
from statistics import mean

class RangePercentageDMA(Metric):

    """
    4) 7 DMA Range Percentage
    The 7 Days Simple Moving Average of the Day’s Price Range Percentage

    5) 30 DMA Range Percentage 
    The 30 Days Simple Moving Average of the Day’s Price Range Percentage

    """

    def __init__(self, algo, name, length, ignore=0):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.ignore = ignore
        self.Values = RollingWindow[float](60)
        self.IsReady = False

    def calculate(self):
        if not self.algorithm.symbols[self.name].metrics['DayPriceRangePercentage'].IsReady:
            return

        self.Values.Add(self.algorithm.symbols[self.name].metrics['DayPriceRangePercentage'].Value)

        if not self.Values.IsReady:
            return

        self.Value = mean(list(self.Values)[self.ignore:self.ignore+self.length])
        self.IsReady = True
# __init__.py
from AlgorithmImports import *
from metrics.Metric import Metric
from statistics import mean

class DMAGapUpDown(Metric):

    """
    40) 7 DMA Gap Up/Down 
    The 7 DMA of the Gap Percentage. 
    The Gap Percentage is the percentage of change of the day open relative to the last day’s close.

    41) 30 DMA Gap Up/Down
    The 30 DMA of the Gap Percentage. 
    The Gap Percentage is the percentage of  change of the day open relative to the last day’s close.

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        gaps = []
        for i in range(self.length):
            last_close = self.algorithm.DayHistory[self.name][i+1].Close
            open_value = self.algorithm.DayHistory[self.name][i].Open
            Value = (open_value - last_close) * 100 / last_close
            gaps.append(Value)

        self.Value = mean(gaps)
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class DayChangePercentage(Metric):

    """
    37) 1 Day Change Percentage 
    The change percentage of the day close relative to the close of day 1 daily bars ago. 

    38) 7 Day Change Percentage 
    The change percentage of the day close relative to the close of day 7 daily bars ago. 

    39) 30 Day Change Percentage 
    The change percentage of the day close relative to the close of the day 30 daily bars ago

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        last_close = self.algorithm.DayHistory[self.name][self.length].Close
        close_value = self.algorithm.DayHistory[self.name][0].Close
        self.Value = (close_value - last_close) * 100 / last_close
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class Last52WeekHighPercentage(Metric):

    """
    14) 52 Week High Percentage
    The percentage of the last 52 Weeks high relative to the last price. 
    (52 Week High - last price) * 100 / last price

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        high_value = max([x.High for x in self.algorithm.WeekHistory[self.name]])
        last_value = self.algorithm.Securities[self.name].Price
        self.Value = (high_value - last_value) * 100 / last_value
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric
from statistics import mean

class MarketOpenChangeDMAPercentage(Metric):

    """
    23) Market Open Change 7 DMA Percentage
    The 7 DMA of the Market Open Change.
    The Market Open change is the percentage change between day open and day close relative to the day open.

    24) Market Open Change 30 DMA Percentage
    The 30 DMA of the Market Open Change.
    The Market Open change is the percentage change between day open and day close relative to the day open.

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        change = []
        for bar in list(self.algorithm.DayHistory[self.name])[:self.length]:
            open_value = bar.Open
            close_value = bar.Close
            Value = (close_value - open_value) * 100 / open_value
            change.append(Value)

        self.Value = mean(change)
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class PercentageUpDownFromOpen(Metric):

    """
    10) Percentage UP/Down From Open 
    The percentage change of price relative to the day open price. 
    (Day Close - Day Open) * 100 / Day Open

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        open_value = self.algorithm.DayHistory[self.name][0].Open
        close_value = self.algorithm.DayHistory[self.name][0].Close
        self.Value = (close_value - open_value) * 100 / open_value
        self.IsReady = True
# __init__.py
from AlgorithmImports import *
from metrics.Metric import Metric

class DMA(Metric):
    '''
    The Day Simple Moving Average of Price

    '''

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.sma = self.algorithm.SMA(name, length, Resolution.Daily)
        self.IsReady=False

    def calculate(self):
        if self.sma.IsReady:
            self.Value=self.sma.Current.Value
            self.IsReady=True
from datetime import time
from AlgorithmImports import *
from metrics.Metric import Metric


class DayHigh(Metric):

    """
    Calculate The Day High of the symbol.

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.Value = None
        self.IsReady = False

    def calculate(self):
        if (
            self.Value is None
            or self.algorithm.SecondHistory[self.name][0].Time.date()
            != self.algorithm.SecondHistory[self.name][1].Time.date()
        ):
            self.Value = self.algorithm.SecondHistory[self.name][0].High
        self.Value = max(self.Value, self.algorithm.SecondHistory[self.name][0].High)
        self.IsReady = True
from datetime import time
from AlgorithmImports import *
from metrics.Metric import Metric


class DayLow(Metric):

    """
    Calculate The Day Low of the symbol.

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.Value = None
        self.IsReady = False

    def calculate(self):
        if (
            self.Value is None
            or self.algorithm.SecondHistory[self.name][0].Time.date()
            != self.algorithm.SecondHistory[self.name][1].Time.date()
        ):
            self.Value = self.algorithm.SecondHistory[self.name][0].Low
        self.Value = min(self.Value, self.algorithm.SecondHistory[self.name][0].Low)
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class OnePercentValue(Metric):

    """
    Calculate One Percent Value of last symbol price. 

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady=False


    def calculate(self):
        self.Value = self.algorithm.Securities[self.name].Price * 0.1
        self.IsReady=True

from AlgorithmImports import *
from metrics.Metric import Metric

class Price(Metric):

    """
    Calculate The last update of the symbol price. 

    """
    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady=False

    def calculate(self):
        self.Value = self.algorithm.Securities[self.name].Price
        self.IsReady=True

# __init__.py
from metrics.Metric import Metric
from AlgorithmImports import *


class FiftenSeconds30DMAVolume(Metric):

    """
    28) 15 Seconds / 30 DMA Volume
    The ratio between the last 15 seconds volume and the 30 DMA volume scaled per 15 seconds.

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        total_vol = sum([bar.Volume for bar in list(self.algorithm.DayHistory[self.name])[:30]])

        dma_15_second = total_vol / 46800

        vol_15_seconds = sum(bar.Volume for bar in self.algorithm.SecondHistory[self.name])

        if dma_15_second == 0:
            return
            
        self.Value = vol_15_seconds / dma_15_second
        self.IsReady = True
from metrics.Metric import Metric
from AlgorithmImports import *

class NetVolumePercentage(Metric):

    """
    29) Day Net Volume Percentage 
    The Day Net Volume Percentage is the Percentage of the positive volume relative to the total volume of the day.
    The positive volume is the volume corresponding to the price bar where the close is equal or greater than the close price of the previous bar. 
    We can use 1 minute bars in this calculation.

    30) Week Net Volume Percentage 
    The Day Net Volume Percentage is the Percentage of the positive volume relative to the total volume of the week.

    31) Month Net Volume Percentage
    The Day Net Volume Percentage is the Percentage of the positive volume relative to the total volume of the month.

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        total_vol = 0
        positive_vol = 0
        last_day = self.algorithm.MinuteHistory[self.name][0].Time.date()
        day_count = 0
        for i in range(self.algorithm.MinuteHistory[self.name].Count):
            if last_day != self.algorithm.MinuteHistory[self.name][i].Time.date():
                day_count += 1
                last_day = self.algorithm.MinuteHistory[self.name][i].Time.date()

            if day_count >= self.length:
                break

            total_vol += self.algorithm.MinuteHistory[self.name][i].Volume
            if self.algorithm.MinuteHistory[self.name][i].Close >= self.algorithm.MinuteHistory[self.name][i+1].Close:
                positive_vol += self.algorithm.MinuteHistory[self.name][i].Volume

        if total_vol == 0:
            return
        
        negative_vol = total_vol - positive_vol
        self.Value = (positive_vol - negative_vol) * 100 / total_vol
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class PercentageAboveDailyVolume(Metric):

    """
    27) Percentage Above Daily Volume
    The Percentage of the end of day accumulated volume estimated using
    the up to current time accumulated volume relative to the 30 DMA Volume.

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        if not self.algorithm.symbols[self.name].metrics['Volume30DMA'].IsReady:
            return
        
        vol_today = 0
        minute_bar_count = 0
        last_day = self.algorithm.MinuteHistory[self.name][0].Time.date()
        for bar in self.algorithm.MinuteHistory[self.name]:
            if bar.Time.date() != last_day:
                break
            vol_today += bar.Volume
            minute_bar_count += 1

        volume_per_minute = vol_today / minute_bar_count
        volume = volume_per_minute * 390
        if volume == 0:
            return
        self.Value = (volume - self.algorithm.symbols[self.name].metrics['Volume30DMA'].Value) * 100 / volume
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class PercentageOfMarketPriceVsVWAP(Metric):

    """
    9) Percentage of Market Price Vs VWAP 
    The percentage difference between last price and Vwap.
    (Price - VWAP) * 100 / Price

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        if not self.algorithm.symbols[self.name].metrics['VWAP'].IsReady:
            return

        self.Value = (self.algorithm.Securities[self.name].Price - self.algorithm.symbols[self.name].metrics['VWAP'].Value) * 100 /\
            self.algorithm.Securities[self.name].Price
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class VWAP(Metric):

    """
    8)  VWAP 
    The volume weighted moving average price.

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo

        symbol = self.algorithm.Securities[name].Symbol
        self.vwap = self.algorithm.VWAP(symbol)

        self.IsReady = False

    def calculate(self):
        if self.vwap.IsReady:
            self.Value = self.vwap.Current.Value
            self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class VolumeChangePercentage(Metric):

    """
    34) 1 Day Volume Change Percentage 
    The percentage change of the current day volume up to the current time relative to the previous day volume up to the same time.

    35) 7 Day Volume Change Percentage 
    The percentage change of the current day volume up to the current time relative to the day volume up to the same time 7 days ago.

    36) 30 Day Volume Change Percentage 
    The percentage change of the current day volume up to the current time relative to the day volume up to the same time 30 days ago.

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        vol_today = 0
        minute_bar_count = 0
        last_day = self.algorithm.MinuteHistory[self.name][0].Time.date()
        for bar in self.algorithm.MinuteHistory[self.name]:
            if bar.Time.date() != last_day:
                break
            vol_today += bar.Volume
            minute_bar_count += 1
        
        if vol_today == 0:
            return
        
        # if the day is not closed yet we compare current volume with the volume of length - 1 bars ago
        length = self.length
        if self.algorithm.MinuteHistory[self.name][0].Time.date() != self.algorithm.DayHistory[self.name][0].Time.date():
            length -= 1

        last_day = self.algorithm.DayHistory[self.name][length].Time.date()

        start_bar = self.get_start_bar(last_day)
        start_bar -= minute_bar_count - 1

        last_vol = 0
        for i in range(minute_bar_count):
            last_vol += self.algorithm.MinuteHistory[self.name][i+start_bar].Volume

        self.Value = (vol_today - last_vol) * 100 / vol_today
        self.IsReady = True

    def get_start_bar(self, date):
        '''
        binary search to get the start bar of minute history of x day ago
        '''
        low = 0
        high = self.algorithm.MinuteHistory[self.name].Count - 1

        while low < high:
            mid = low + (high - low + 1) // 2

            if self.algorithm.MinuteHistory[self.name][mid].Time.date() < date:
                high = mid - 1
            else:
                low = mid
        return low
from AlgorithmImports import *
from metrics.Metric import Metric
from statistics import mean

class VolumeDMA(Metric):

    """
    32) 7 DMA Volume 
    The 7 Day Simple Moving Average of Volume

    33) 30 DMA Volume 
    The 30 Day Simple Moving Average of Volume

    """

    def __init__(self, algo, name, length):
        self.name = name
        self.algorithm = algo
        self.length = length
        self.IsReady = False

    def calculate(self):
        self.Value = mean([bar.Volume for bar in list(self.algorithm.DayHistory[self.name])[:self.length]])
        self.IsReady = True
from AlgorithmImports import *
from metrics.Metric import Metric

class VolumePerTimeMultipleVs30DMA(Metric):

    """
    11) Volume Per Time Multiple Vs 30DMA Volume Per Time Multiple 
    The day volume per minute calculated by the total daily volume and dividing it by the number of minutes passed in the day. 

    It is then divided by its 30 Day Simple Moving Average to get the volume multiple.

    """

    def __init__(self, algo, name):
        self.name = name
        self.algorithm = algo
        self.IsReady = False

    def calculate(self):
        vol_today = sum([x.Volume for x in self.algorithm.MinuteHistory[self.name]
                         if x.Time.date() == self.algorithm.MinuteHistory[self.name][0].Time.date()]) /\
            len([x for x in self.algorithm.MinuteHistory[self.name]
                if x.Time.date() == self.algorithm.MinuteHistory[self.name][0].Time.date()])
        bar_count = 0
        vol_30_day = 0
        days_count = 0
        last_day = self.algorithm.MinuteHistory[self.name][0].Time.date()
        for bar in self.algorithm.MinuteHistory[self.name]:
            if last_day != bar.Time.date():
                days_count += 1
                last_day = bar.Time.date()
            if days_count > 30:
                break
            if not days_count:
                continue
            if bar.Time.time() <= self.algorithm.MinuteHistory[self.name][0].Time.time():
                bar_count += 1
                vol_30_day += bar.Volume

        avg_vol_30_day = vol_30_day / bar_count

        self.Value = vol_today / avg_vol_30_day
        self.IsReady = True
# __init__.py
# __init__.py
from asyncio import FastChildWatcher
from AlgorithmImports import *
from config import *
from datetime import datetime
from trades.ITrade import Trade
from typing import List

class Symbol:

    def __init__(self, algo, name):
        self.algorithm = algo
        self.last_trade= [datetime.min,datetime.min,datetime.min,datetime.min,datetime.min]
        self.name = name
        self.metrics = {}
        self.trades: List[Trade] = []

    def addMetric(self):
        config_metrics=self.algorithm.config.metrics
        for key in config_metrics:
            for item in config_metrics[key]:
                chart_name=item[0]
                if len(item)==3:
                    self.metrics[chart_name]=item[1](self.algorithm,self.name,*item[2])
                else:
                    self.metrics[chart_name]=item[1](self.algorithm,self.name)

    def addTrades(self):
        config_trades = self.algorithm.config.trades
        for trade in config_trades:
            self.trades.append(trade(self))

    def update_trade(self):
        for trade in self.trades:
            if trade.in_order:
                trade.update()

    def trade(self):
        if self.in_trade:
            return
        for trade in self.trades:
            if self.in_trade is False:
                trade.entry_order()
    
    def handle_order_event(self, orderEvent: OrderEvent):
        for trade in self.trades:
            if trade.in_order:
                trade.handle_order_event(orderEvent)
        
    def update(self,type):
        for metric in [item[0] for item in self.algorithm.config.metrics[type]]:
            self.metrics[metric].calculate()
            self.plot(type)

    def plot(self,type):
        for metric in [item[0] for item in self.algorithm.config.metrics[type]]:
            if metric in self.algorithm.config.plot_metrics:
                chart=Chart(f"{metric}")
                self.algorithm.AddChart(chart)

                if self.metrics[metric].IsReady :
                    self.algorithm.Plot(f"{metric}", f"{self.name}", self.metrics[metric].Value)
            
    @property
    def in_trade(self):
        result = False
        for trade in self.trades:
            result |= trade.in_order
        return result
from AlgorithmImports import *
from config import Config


class Condition:
    def __init__(self):
        self.parameters = Config.set_parameters()

    def base_condition(self, symbol, C, SameConditionTimeC):
        "Time Since the last Entry for the Symbol for Trade 1 is at least SameConditionTimeC1 minutes"
        id = int(C[1]) - 1
        if (
            self.parameters["PauseAlgo"] == False
            and self.open_position(symbol) == False
            and self.parameters["Trading Algorithm"]
            and self.parameters[C]
            and (symbol.algorithm.Time - symbol.last_trade[id]).seconds / 60
            >= self.parameters[SameConditionTimeC]
        ):
            return True
        return False

    def open_position(self, symbol):
        "There is open position for the Symbol"
        symbol_open_orders = symbol.algorithm.Transactions.GetOpenOrders(symbol.name)
        if len(symbol_open_orders) == 0:
            return False
        return True

    def percentage_of_market_price_vs_vwap_condition(self, symbol):
        "Percentage of Market Price Vs Vwap is less than 0 and has absolute value greater than 7 DMA Range Price * VWAP_PCT"

        market_price_vwmp = symbol.metrics["PercentageOfMarketPriceVsVWAP"]
        price_change_7dma = symbol.metrics["DayPercentageChangeOf7DMARangePercentage"]

        if market_price_vwmp.IsReady and price_change_7dma.IsReady:
            return (market_price_vwmp.Value, price_change_7dma.Value)
        return (-1, -1)

    def days_price_range_percentage_condition(self, symbol):
        "Day’s Price Range Percentage is equal to or less than( -1 * (Parameter 1 / 100) * 30 DMA Range Price)"
        price_day_range = symbol.metrics["PricePercentageOfDayRange"]
        price_30day_range = symbol.metrics["PricePercentageOf30DayRange"]

        if price_day_range.IsReady and price_30day_range.IsReady:
            return (price_day_range.Value, price_30day_range.Value)
        return (-1, -1)

    def ratio_of_the_Maximum_Down_Percentage(self, symbol):
        """
        The ratio of the Maximum Down Percentage in the last 30 minutes of the day to the 30 DMA Range Price Percentage
        is less than or equal (-1 * Parameter 3) / 100.0
        """
        price_30day_range = symbol.metrics["PricePercentageOf30DayRange"]
        if price_30day_range.IsReady == False:
            return False
        last_30_minutes = list(symbol.algorithm.MinuteHistory[symbol.name])[:30]
        max_high = 0
        max_down_percentage = 0

        for v in reversed(last_30_minutes):
            if v.High > max_high:
                max_high = v.High
                continue
            if max_high > v.Low:
                max_down_percentage = max(max_down_percentage, (max_high - v.Low) * 100 / max_high)

        ratio = max_down_percentage / price_30day_range.Value

        return ratio <= (-1 * self.parameters["Parameter 3"] / 100)

    def last_bar_makes_a_new_day_low(self, symbol):
        low = symbol.algorithm.SecondHistory[symbol.name][0].Low
        return low == symbol.metrics["DayLow"]

    def last_bar_makes_a_new_day_high(self, symbol):
        high = symbol.algorithm.SecondHistory[symbol.name][0].High
        return high == symbol.metrics["DayHigh"]

    def rally_condition(self, symbol):
        price = symbol.metrics["Price"]
        price_day_range = symbol.metrics["PricePercentageOfDayRange"]

        if price_day_range.IsReady:
            percentage_increase = 0
            low = 90000000
            high = 0
            last_day = symbol.algorithm.MinuteHistory[symbol.name][0].Time.date()
            lst_of_bars = []
            for bar in symbol.algorithm.MinuteHistory[symbol.name]:
                if bar.Time.date() != last_day:
                    break
                lst_of_bars.append(bar)

            lst_of_bars.reverse()

            # part one
            for bar in lst_of_bars:
                if bar.Low < low:
                    low = bar.Low
                    high = 0
                    percentage_increase = 0
                    continue

                if bar.High > high:
                    high = bar.High
                    percentage_increase = (high - low) * 100 / low

            percentage_a = float(percentage_increase / price_day_range.Value) * 100

            # part 2
            if high == 0:
                precentage_b = abs(
                    float(lst_of_bars[-1].High - lst_of_bars[-1].Low) * 100 / lst_of_bars[-1].High
                )
            else:
                precentage_b = abs(float(high - lst_of_bars[-1].Low) * 100 / high)

            precentage_b = float(precentage_b / price_day_range.Value) * 100
            # conditions
            reset = False
            condition_1 = False
            condition_2 = False

            if (
                self.parameters["Rally_X_Min_PCT"]
                <= percentage_a
                <= self.parameters["Rally_X_Max_PCT"]
            ):
                condition_1 = True

            if precentage_b >= self.parameters["Rally_Y_PCT"]:
                condition_2 = True

            if percentage_a > self.parameters["Rally_X_Max_PCT"]:
                reset = True

            return {"reset": reset, "condition": condition_1 and condition_2}
        else:
            return {"reset": False, "condition": False}

    def short_rally_condition(self, symbol):
        price = symbol.metrics["Price"]
        price_day_range = symbol.metrics["PricePercentageOfDayRange"]

        if price_day_range.IsReady:
            percentage_increase = 0
            low = 90000000
            high = 0
            last_day = symbol.algorithm.MinuteHistory[symbol.name][0].Time.date()
            lst_of_bars = []
            for bar in symbol.algorithm.MinuteHistory[symbol.name]:
                if bar.Time.date() != last_day:
                    break
                lst_of_bars.append(bar)

            lst_of_bars.reverse()

            # part one
            for bar in lst_of_bars:
                if bar.High > high:
                    high = bar.High
                    low = 90000000
                    percentage_increase = 0
                    continue

                if bar.Low < low:
                    low = bar.Low
                    percentage_increase = abs(high - low) * 100 / high

            percentage_a = float(percentage_increase / price_day_range.Value) * 100

            # part 2
            if low == 90000000:
                precentage_b = abs(
                    float(lst_of_bars[-1].High - lst_of_bars[-1].Low) * 100 / lst_of_bars[-1].Low
                )
            else:
                precentage_b = abs(float(lst_of_bars[-1].High - low) * 100 / low)

            precentage_b = float(precentage_b / price_day_range.Value) * 100

            # conditions
            reset = False
            condition_1 = False
            condition_2 = False

            if (
                self.parameters["Rally_X_Min_PCT"]
                <= percentage_a
                <= self.parameters["Rally_X_Max_PCT"]
            ):
                condition_1 = True

            if precentage_b >= self.parameters["Rally_Y_PCT"]:
                condition_2 = True

            if percentage_a > self.parameters["Rally_X_Min_PCT"]:
                reset = True

            return {"reset": reset, "condition": condition_1 and condition_2}
        else:
            return {"reset": False, "condition": False}
from abc import ABC, abstractmethod

from AlgorithmImports import *

from symbols.symbol import Symbol


class Trade(ABC):
    def __init__(self, symbol: Symbol) -> None:
        self.symbol: Symbol = symbol
        self.algorithm: QCAlgorithm = symbol.algorithm
        self.ticket: OrderTicket = None
        self.parameters = self.algorithm.config.set_parameters()

    def base_condition(self, C, SameConditionTimeC):
        id = int(C[1]) - 1
        if (
            self.parameters["PauseAlgo"] == False
            and self.symbol.in_trade == False
            and self.parameters["Trading Algorithm"]
            and self.parameters[C]
            and (self.algorithm.Time - self.symbol.last_trade[id]).seconds / 60
            >= self.parameters[SameConditionTimeC]
        ):
            return True
        return False


    @abstractmethod
    def condition(self):
        pass

    @abstractmethod
    def entry_order(self):
        pass

    @abstractmethod
    def exit_order(self):
        pass

    @abstractmethod
    def update(self):
        pass

    def handle_order_event(self, orderEvent: OrderEvent):
        if orderEvent.Status == OrderStatus.Filled:
            if orderEvent.OrderId == self.ticket.OrderId:
                self.exit_order()
            else:
                self.Transactions.CancelOpenOrders(self.symbol.name)
                self.ticket = None

    @property
    def in_order(self):
        return self.ticket is not None


class LongTrade(Trade):
    def __init__(self, symbol: Symbol) -> None:
        super().__init__(symbol)

    def rally_condition(self):
        price = self.symbol.metrics["Price"]
        price_day_range = self.symbol.metrics["PricePercentageOfDayRange"]

        if price_day_range.IsReady:
            percentage_increase = 0
            low = 90000000
            high = 0
            last_day = self.symbol.algorithm.MinuteHistory[self.symbol.name][0].Time.date()
            lst_of_bars = []
            for bar in self.symbol.algorithm.MinuteHistory[self.symbol.name]:
                if bar.Time.date() != last_day:
                    break
                lst_of_bars.append(bar)

            lst_of_bars.reverse()

            # part one
            for bar in lst_of_bars:
                if bar.Low < low:
                    low = bar.Low
                    high = 0
                    percentage_increase = 0
                    continue

                if bar.High > high:
                    high = bar.High
                    percentage_increase = (high - low) * 100 / low

            percentage_a = float(percentage_increase / price_day_range.Value) * 100

            # part 2
            if high == 0:
                precentage_b = abs(
                    float(lst_of_bars[-1].High - lst_of_bars[-1].Low) * 100 / lst_of_bars[-1].High
                )
            else:
                precentage_b = abs(float(high - lst_of_bars[-1].Low) * 100 / high)

            precentage_b = float(precentage_b / price_day_range.Value) * 100
            # conditions
            reset = False
            condition_1 = False
            condition_2 = False

            if (
                self.parameters["Rally_X_Min_PCT"]
                <= percentage_a
                <= self.parameters["Rally_X_Max_PCT"]
            ):
                condition_1 = True

            if precentage_b >= self.parameters["Rally_Y_PCT"]:
                condition_2 = True

            if percentage_a > self.parameters["Rally_X_Max_PCT"]:
                reset = True

            return {"reset": reset, "condition": condition_1 and condition_2}
        else:
            return {"reset": False, "condition": False}

    def condition(self):
        return super().condition()

    def entry_order(self):
        return super().entry_order()

    def exit_order(self):
        return super().exit_order()

    def update(self):
        return super().update()


class ShortTrade(Trade):
    def __init__(self, symbol: Symbol) -> None:
        super().__init__(symbol)

    def rally_condition(self):
        price = self.symbol.metrics["Price"]
        price_day_range = self.symbol.metrics["PricePercentageOfDayRange"]

        if price_day_range.IsReady:
            percentage_increase = 0
            low = 90000000
            high = 0
            last_day = self.symbol.algorithm.MinuteHistory[self.symbol.name][0].Time.date()
            lst_of_bars = []
            for bar in self.symbol.algorithm.MinuteHistory[self.symbol.name]:
                if bar.Time.date() != last_day:
                    break
                lst_of_bars.append(bar)

            lst_of_bars.reverse()

            # part one
            for bar in lst_of_bars:
                if bar.High > high:
                    high = bar.High
                    low = 90000000
                    percentage_increase = 0
                    continue

                if bar.Low < low:
                    low = bar.Low
                    percentage_increase = abs(high - low) * 100 / high

            percentage_a = float(percentage_increase / price_day_range.Value) * 100

            # part 2
            if low == 90000000:
                precentage_b = abs(
                    float(lst_of_bars[-1].High - lst_of_bars[-1].Low) * 100 / lst_of_bars[-1].Low
                )
            else:
                precentage_b = abs(float(lst_of_bars[-1].High - low) * 100 / low)

            precentage_b = float(precentage_b / price_day_range.Value) * 100

            # conditions
            reset = False
            condition_1 = False
            condition_2 = False

            if (
                self.parameters["Rally_X_Min_PCT"]
                <= percentage_a
                <= self.parameters["Rally_X_Max_PCT"]
            ):
                condition_1 = True

            if precentage_b >= self.parameters["Rally_Y_PCT"]:
                condition_2 = True

            if percentage_a > self.parameters["Rally_X_Max_PCT"]:
                reset = True

            return {"reset": reset, "condition": condition_1 and condition_2}
        else:
            return {"reset": False, "condition": False}

    def condition(self):
        return super().condition()

    def entry_order(self):
        return super().entry_order()

    def exit_order(self):
        return super().exit_order()

    def update(self):
        return super().update()
# init
from AlgorithmImports import *
from trades.ITrade import *


class TradeFive(LongTrade):
    def __init__(self, symbol):
        super().__init__(symbol)
        self.condition1_5 = False
        self.condition6 = False
        self.condition7 = False
        self.condition8 = False

    def percentage_of_market_price_vs_vwap_condition(self):

        market_price_vwmp = self.symbol.metrics["PercentageOfMarketPriceVsVWAP"]
        price_change_7dma = self.symbol.metrics["DayPercentageChangeOf7DMARangePercentage"]

        if market_price_vwmp.IsReady and price_change_7dma.IsReady:
            return market_price_vwmp.Value > (
                price_change_7dma.Value * self.parameters["VWAP_PCT"]
            )
        return False

    def days_price_range_percentage_condition(self):

        price_day_range = self.symbol.metrics["PricePercentageOfDayRange"]
        price_30day_range = self.symbol.metrics["PricePercentageOf30DayRange"]

        if price_day_range.IsReady and price_30day_range.IsReady:
            return (
                price_day_range.Value
                >= (self.parameters["Parameter 2"] / 100) * price_30day_range.Value
            )
        return False

    def last_bar_makes_a_new_day_high(self):
        high = self.symbol.algorithm.SecondHistory[self.symbol.name][0].High
        return high == self.symbol.metrics["DayHigh"]

    def condition(self):
        if self.condition1_5 and self.condition6 and self.condition7:
            data = self.rally_condition()
            if data["condition"]:
                return True

            if data["reset"] == False:
                self.condition1_5 = False
                self.condition6 = False
                self.condition7 = False
                self.condition8 = False
            return False

        else:
            self.condition1_5 = self.base_condition("C5", "SameConditionTimeC5")
            self.condition6 = self.percentage_of_market_price_vs_vwap_condition
            self.condition7 = self.last_bar_makes_a_new_day_high()
            self.condition8 = self.days_price_range_percentage_condition()
            return False

    def entry_order(self):
        if self.in_order or self.condition() is False:
            return
        if not self.symbol.metrics["DayLow"].IsReady:
            return

        stop_price = self.Securities[self.symbol].Price - (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])
        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        self.ticket = self.StopLimitOrder(self.symbol, quantity, stop_price, limit_price)

    def update(self):
        if not self.in_order:
            return

        if self.ticket.Status == OrderStatus.Filled:
            return

        stop_price = self.Securities[self.symbol].Price - (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])

        if stop_price > self.ticket.Get(OrderField.StopPrice):
            return

        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price - limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        update_settings = UpdateOrderFields()
        update_settings.StopPrice = stop_price
        update_settings.LimitPrice = limit_price
        update_settings.Quantity = quantity
        response = self.ticket.Update(update_settings)

        if not response.IsSuccess:
            self.Debug("Order failed to update")

    def exit_order(self):
        size: float = -self.ticket.QuantityFilled * (self.algorithm.config["SharesToSell"] / 100)
        fill_price: float = self.ticket.AverageFillPrice
        tp_limit_price = (
            fill_price
            - fill_price
            * (self.algorithm.config["ProfitTakeC5"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.LimitOrder(self.symbol.name, size, tp_limit_price)

        sl_price = (
            fill_price
            + fill_price
            * (self.algorithm.config["StopLoss"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.StopMarketOrder(self.symbol.name, size, sl_price)
from AlgorithmImports import *
from trades.ITrade import *


class TradeFour(ShortTrade):
    def __init__(self, symbol):
        super().__init__(symbol)
        self.condition1_5 = False
        self.condition6 = False
        self.condition7 = False

    def percentage_of_market_price_vs_vwap_condition(self):

        market_price_vwmp = self.symbol.metrics["PercentageOfMarketPriceVsVWAP"]
        price_change_7dma = self.symbol.metrics["DayPercentageChangeOf7DMARangePercentage"]

        if market_price_vwmp.IsReady and price_change_7dma.IsReady:
            return market_price_vwmp.Value >= (
                price_change_7dma.Value * self.parameters["VWAP_PCT"]
            )
        return False

    def days_price_range_percentage_condition(self):
        price_day_range = self.symbol.metrics["PricePercentageOfDayRange"]
        price_30day_range = self.symbol.metrics["PricePercentageOf30DayRange"]

        if price_day_range.IsReady and price_30day_range.IsReady:
            return (
                price_day_range.Value
                >= (self.parameters["Parameter 1"] / 100) * price_30day_range.Value
            )
        return False

    def condition(self):
        if self.condition1_5 and self.condition6 and self.condition7:
            data = self.rally_condition()
            if data["condition"]:
                return True

            if data["reset"] == False:
                self.condition1_5 = False
                self.condition6 = False
                self.condition7 = False
            return False

        else:
            self.condition1_5 = self.base_condition("C4", "SameConditionTimeC4")
            self.condition6 = self.percentage_of_market_price_vs_vwap_condition()
            self.condition7 = self.days_price_range_percentage_condition()
            return False

    def entry_order(self):
        if self.in_order or self.condition() is False:
            return
        if not self.symbol.metrics["DayLow"].IsReady:
            return

        stop_price = self.Securities[self.symbol].Price - (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])
        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price - limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        self.ticket = self.StopLimitOrder(self.symbol, quantity, stop_price, limit_price)

    def update(self):
        if not self.in_order:
            return

        if self.ticket.Status == OrderStatus.Filled:
            return

        stop_price = self.Securities[self.symbol].Price - (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])

        if stop_price > self.ticket.Get(OrderField.StopPrice):
            return

        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        update_settings = UpdateOrderFields()
        update_settings.StopPrice = stop_price
        update_settings.LimitPrice = limit_price
        update_settings.Quantity = quantity
        response = self.ticket.Update(update_settings)

        if not response.IsSuccess:
            self.Debug("Order failed to update")

    def exit_order(self):
        size: float = -self.ticket.QuantityFilled * (self.algorithm.config["SharesToSell"] / 100)
        fill_price: float = self.ticket.AverageFillPrice
        tp_limit_price = (
            fill_price
            - fill_price
            * (self.algorithm.config["ProfitTakeC4"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.LimitOrder(self.symbol.name, size, tp_limit_price)

        sl_price = (
            fill_price
            + fill_price
            * (self.algorithm.config["StopLoss"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.StopMarketOrder(self.symbol.name, size, sl_price)
from AlgorithmImports import *
from trades.ITrade import *


class TradeOne(LongTrade):
    def __init__(self, symbol):
        super().__init__(symbol)
        self.condition1_5 = False
        self.condition6 = False
        self.condition7 = False

    def percentage_of_market_price_vs_vwap_condition(self):

        market_price_vwmp = self.symbol.metrics["PercentageOfMarketPriceVsVWAP"]
        price_change_7dma = self.symbol.metrics["DayPercentageChangeOf7DMARangePercentage"]

        if market_price_vwmp.IsReady and price_change_7dma.IsReady:
            return market_price_vwmp.Value < 0 and abs(market_price_vwmp.Value) > (
                price_change_7dma.Value * self.parameters["VWAP_PCT"]
            )
        return False

    def days_price_range_percentage_condition(self):
        
        price_day_range = self.symbol.metrics["PricePercentageOfDayRange"]
        price_30day_range = self.symbol.metrics["PricePercentageOf30DayRange"]

        if price_day_range.IsReady and price_30day_range.IsReady:
            return (
                price_day_range.Value
                <= -1 * (self.parameters["Parameter 1"] / 100) * price_30day_range.Value
            )
        return False

    def condition(self):
        if self.condition1_5 and self.condition6 and self.condition7:
            data = self.rally_condition()
            if data["condition"]:
                return True

            if data["reset"] == False:
                self.condition1_5 = False
                self.condition6 = False
                self.condition7 = False
            return False

        else:
            self.condition1_5 = self.base_condition("C1", "SameConditionTimeC1")
            self.condition6 = self.percentage_of_market_price_vs_vwap_condition()
            self.condition7 = self.days_price_range_percentage_condition()
            return False

    def entry_order(self):
        if self.in_order or self.condition() is False:
            return
        if not self.symbol.metrics["DayLow"].IsReady:
            return

        stop_price = self.Securities[self.symbol].Price + (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])
        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        self.ticket = self.StopLimitOrder(self.symbol, quantity, stop_price, limit_price)

    def update(self):
        if not self.in_order:
            return

        if self.ticket.Status == OrderStatus.Filled:
            return

        stop_price = self.Securities[self.symbol].Price + (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])

        if stop_price < self.ticket.Get(OrderField.StopPrice):
            return

        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        update_settings = UpdateOrderFields()
        update_settings.StopPrice = stop_price
        update_settings.LimitPrice = limit_price
        update_settings.Quantity = quantity
        response = self.ticket.Update(update_settings)

        if not response.IsSuccess:
            self.Debug("Order failed to update")

    def exit_order(self):
        size: float = -self.ticket.QuantityFilled * (self.algorithm.config["SharesToSell"] / 100)
        fill_price: float = self.ticket.AverageFillPrice
        tp_limit_price = (
            fill_price
            + fill_price
            * (self.algorithm.config["ProfitTakeC1"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.LimitOrder(self.symbol.name, size, tp_limit_price)

        sl_price = (
            fill_price
            - fill_price
            * (self.algorithm.config["StopLoss"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.StopMarketOrder(self.symbol.name, size, sl_price)
from AlgorithmImports import *
from trades.ITrade import *


class TradeThree(LongTrade):
    def __init__(self, symbol):
        super().__init__(symbol)
        self.condition1_5 = False
        self.condition6 = False

    def ratio_of_the_Maximum_Down_Percentage(self):
        
        price_30day_range = self.symbol.metrics["PricePercentageOf30DayRange"]
        if price_30day_range.IsReady == False:
            return False
        last_30_minutes = list(self.symbol.algorithm.MinuteHistory[self.symbol.name])[:30]
        max_high = 0
        max_down_percentage = 0

        for v in reversed(last_30_minutes):
            if v.High > max_high:
                max_high = v.High
                continue
            if max_high > v.Low:
                max_down_percentage = max(max_down_percentage, (max_high - v.Low) * 100 / max_high)

        ratio = max_down_percentage / price_30day_range.Value
        return ratio <= (-1 * self.parameters["Parameter 3"] / 100)

    def condition(self):
        self.condition1_5 = self.condition.base_condition("C3", "SameConditionTimeC3")
        self.condition6 = self.condition.ratio_of_the_Maximum_Down_Percentage()

        return self.condition1_5 and self.condition6

    def entry_order(self):
        if self.in_order or self.condition() is False:
            return
        if not self.symbol.metrics["DayLow"].IsReady:
            return

        stop_price = self.Securities[self.symbol].Price + (
            self.algorithm.config["Parameter 5"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])
        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        self.ticket = self.StopLimitOrder(self.symbol, quantity, stop_price, limit_price)

    def update(self):
        if not self.in_order:
            return

        if self.ticket.Status == OrderStatus.Filled:
            return

        stop_price = self.Securities[self.symbol].Price + (
            self.algorithm.config["Parameter 5"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])

        if stop_price < self.ticket.Get(OrderField.StopPrice):
            return

        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        update_settings = UpdateOrderFields()
        update_settings.StopPrice = stop_price
        update_settings.LimitPrice = limit_price
        update_settings.Quantity = quantity
        response = self.ticket.Update(update_settings)

        if not response.IsSuccess:
            self.Debug("Order failed to update")

    def exit_order(self):
        size: float = -self.ticket.QuantityFilled * (self.algorithm.config["SharesToSell"] / 100)
        fill_price: float = self.ticket.AverageFillPrice
        tp_limit_price = (
            fill_price
            + fill_price
            * (self.algorithm.config["ProfitTakeC3"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.LimitOrder(self.symbol.name, size, tp_limit_price)

        sl_price = (
            fill_price
            - fill_price
            * (self.algorithm.config["StopLoss"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.StopMarketOrder(self.symbol.name, size, sl_price)
from AlgorithmImports import *
from trades.ITrade import *


class TradeTwo(LongTrade):
    def __init__(self, symbol):
        super().__init__(symbol)
        self.condition1_5 = False
        self.condition6 = False
        self.condition7 = False
        self.condition8 = False

    def percentage_of_market_price_vs_vwap_condition(self):

        market_price_vwmp = self.symbol.metrics["PercentageOfMarketPriceVsVWAP"]
        price_change_7dma = self.symbol.metrics["DayPercentageChangeOf7DMARangePercentage"]

        if market_price_vwmp.IsReady and price_change_7dma.IsReady:
            return market_price_vwmp.Value < 0 and abs(market_price_vwmp.Value) > (
                price_change_7dma.Value * self.parameters["VWAP_PCT"]
            )
        return False

    def days_price_range_percentage_condition(self):
        
        price_day_range = self.symbol.metrics["PricePercentageOfDayRange"]
        price_30day_range = self.symbol.metrics["PricePercentageOf30DayRange"]

        if price_day_range.IsReady and price_30day_range.IsReady:
            return (
                price_day_range.Value
                >= (self.parameters["Parameter 2"] / 100) * price_30day_range.Value
            )
        return False
    
    def last_bar_makes_a_new_day_low(self):
        low = self.symbol.algorithm.SecondHistory[self.symbol.name][0].Low
        return low == self.symbol.metrics["DayLow"]

    def condition(self):
        if self.condition1_5 and self.condition6 and self.condition7 and self.condition8:
            data = self.rally_condition()
            if data["condition"]:
                return True

            if data["reset"] == False:
                self.condition1_5 = False
                self.condition6 = False
                self.condition7 = False
                self.condition8 = False
            return False

        else:
            self.condition1_5 = self.base_condition("C2", "SameConditionTimeC2")
            self.condition6 = self.percentage_of_market_price_vs_vwap_condition()
            self.condition7 = self.last_bar_makes_a_new_day_low()
            self.condition8 = self.days_price_range_percentage_condition()
            return False

    def entry_order(self):
        if self.in_order or self.condition() is False:
            return
        if not self.symbol.metrics["DayLow"].IsReady:
            return

        stop_price = self.Securities[self.symbol].Price + (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])
        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        self.ticket = self.StopLimitOrder(self.symbol, quantity, stop_price, limit_price)

    def update(self):
        if not self.in_order:
            return

        if self.ticket.Status == OrderStatus.Filled:
            return

        stop_price = self.Securities[self.symbol].Price + (
            self.algorithm.config["Parameter 4"] / 100
        ) * (self.symbol.metrics["DayHigh"] - self.symbol.metrics["DayLow"])

        if stop_price < self.ticket.Get(OrderField.StopPrice):
            return

        limit_price_offset = (self.parameters["OffsetPCT"] / 100) * stop_price
        limit_price = stop_price + limit_price_offset
        quantity = self.algorithm.config["CashRisk-1"] // limit_price

        update_settings = UpdateOrderFields()
        update_settings.StopPrice = stop_price
        update_settings.LimitPrice = limit_price
        update_settings.Quantity = quantity
        response = self.ticket.Update(update_settings)

        if not response.IsSuccess:
            self.Debug("Order failed to update")

    def exit_order(self):
        size: float = -self.ticket.QuantityFilled * (self.algorithm.config["SharesToSell"] / 100)
        fill_price: float = self.ticket.AverageFillPrice
        tp_limit_price = (
            fill_price
            + fill_price
            * (self.algorithm.config["ProfitTakeC2"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.LimitOrder(self.symbol.name, size, tp_limit_price)

        sl_price = (
            fill_price
            - fill_price
            * (self.algorithm.config["StopLoss"] / 100)
            * self.symbol.metrics["RangePercentage30DMA"]
        )
        self.algorithm.StopMarketOrder(self.symbol.name, size, sl_price)
# init