Overall Statistics
Total Trades
23
Average Win
1.11%
Average Loss
-4.99%
Compounding Annual Return
6.373%
Drawdown
7.500%
Expectancy
0.111
Net Profit
5.851%
Sharpe Ratio
0.769
Probabilistic Sharpe Ratio
39.483%
Loss Rate
9%
Win Rate
91%
Profit-Loss Ratio
0.22
Alpha
0.035
Beta
0.096
Annual Standard Deviation
0.07
Annual Variance
0.005
Information Ratio
-0.482
Tracking Error
0.289
Treynor Ratio
0.563
Total Fees
$0.00
Estimated Strategy Capacity
$120000.00
Lowest Capacity Asset
USDCAD 8G
"""
*I identify Support/Resistance(S/R) off the daily timeframe.
*Identify S/R off the 4HR timeframe
*I use two indicators RSI and MACD with the default settings.
*I trade using 4HR charts.

For me to open a buy position…
The RSI has to be crossing and the candle closed above the value of 50.
The MACD line has to be above the signal line showing it’s starting to diverge
The price can’t be pushing up against a resistance zone. I put more emphasis on the Daily S/R zone than I do the 4HR S/R zone but still respect it.

For me to open a sell position…
The RSI has to be crossing and the candle closed below the value of 50.
The MACD line has to be below the signal line showing it’s starting to diverge
The price can’t be pushing down against a support zone. I put more emphasis on the Daily S/R zone than I do the 4HR S/R zone but still respect it.
"""
from datetime import datetime,timedelta
import numpy as np
from dailyhours import SupportResistance

Macdlong = None
AboveSupport = None
BelowResistance = None

class MeasuredApricot(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 1, 30)  # Set Start Date
        self.SetEndDate(2020, 12, 30)
        self.SetCash(100000)  # Set Strategy Cash
        
        self.ticker = "USDCAD"
        # Rolling Windows to hold bar close data keyed by symbol
        self.Data = {}

        #for ticker in tickers:
        symbol = self.AddForex(self.ticker, Resolution.Hour, Market.Oanda).Symbol
        self.Data[symbol] = SymbolData(self, symbol)
            
        self.tolerance = 0.0025
        
        self.toleranceR = 0.986761994
        self.toleranceS = 1.004000555
            
        self.stopLossLevel = -0.05 # stop loss percentage 
        self.stopProfitLevel = 0.01# stop profit percentage
        
    
            
        self.SetWarmUp(50, Resolution.Hour)
        
 


    def OnData(self, data):
        
        if self.IsWarmingUp: #Data to warm up the algo is being collected.
            return
        
        for symbol, symbolData in self.Data.items(): #Return the dictionary's key-value pairs:
            if not (data.ContainsKey(symbol) and data[symbol] is not None and symbolData.IsReady):
                continue
            
            MACD = symbolData.macd.Current.Value
            MACDfast = symbolData.macd.Fast.Current.Value
            RSI = symbolData.rsi.Current.Value
            current_price = data[symbol].Close
            
            signalDeltaPercent = (MACD - MACD)/MACDfast
            
            #closestSupportZone = self.SupportResistance.NextSupport()
            #closestResistanceZone = self.SupportResistance.NextResistance()
            

            if self.Portfolio[symbol].Invested:
                
                if self.isLong:
                    condStopProfit = (current_price - self.buyInPrice)/self.buyInPrice > self.stopProfitLevel
                    condStopLoss = (current_price - self.buyInPrice)/self.buyInPrice < self.stopLossLevel
                    if condStopProfit:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Long Position Stop Profit at {current_price}")
                        
                    if condStopLoss:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Long Position Stop Loss at {current_price}")
                else:
                    condStopProfit = (self.sellInPrice - current_price)/self.sellInPrice > self.stopProfitLevel
                    condStopLoss = (self.sellInPrice - current_price)/self.sellInPrice < self.stopLossLevel
                    if condStopProfit:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Short Position Stop Profit at {current_price}")
                        
                    if condStopLoss:
                        self.Liquidate(symbol)
                        self.Log(f"{self.Time} Short Position Stop Loss at {current_price}")
            
            
            
            if not self.Portfolio[symbol].Invested:
                
                MacdLong = signalDeltaPercent > self.tolerance
                #Above Support = current_price > closestSupportZone * self.toleranceS
                #Below Resistance = current_price < closestResistanceZone * self.toleranceR
                ### tolerance = will be dependent on the minimum number of pips before a r/s level
                
                if RSI > 50 and Macdlong: #Below Resistance:
                    self.SetHoldings(symbol, 1)
                    # get buy-in price for trailing stop loss/profit
                    self.buyInPrice = current_price
                    # entered long position
                    self.isLong = True
                    self.Log(f"{self.Time} Entered Long Position at {current_price}")
                        
                if RSI < 50  and not Macdlong: #Above Support: 
                    self.SetHoldings(symbol, -1)
                    # get sell-in price for trailing stop loss/profit
                    self.sellInPrice = current_price
                    # entered short position
                    self.isLong = False
                    self.Log(f"{self.Time} Entered Short Position at {current_price}")
                        
                    
class SymbolData:
    def __init__(self, algorithm, symbol):
        self.macd = MovingAverageConvergenceDivergence(12,26,9)
        self.rsi = RelativeStrengthIndex(14)
        
        self.macdWindow = RollingWindow[IndicatorDataPoint](2)   #setting the Rolling Window for the fast MACD indicator, takes two values
        algorithm.RegisterIndicator(symbol, self.macd, timedelta(hours=4))
        self.macd.Updated += self.MacdUpdated                    #Updating those two values
        
        self.rsiWindow = RollingWindow[IndicatorDataPoint](2)   #setting the Rolling Window for the slow SMA indicator, takes two values
        algorithm.RegisterIndicator(symbol, self.rsi, timedelta(hours=4))
        self.rsi.Updated += self.RsiUpdated                    #Updating those two values
        
        self.closeWindow = RollingWindow[float](21)
        
        # Add consolidator to track rolling close prices
        self.consolidator = QuoteBarConsolidator(4)
        self.consolidator.DataConsolidated += self.CloseUpdated
        algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator)
        

    def MacdUpdated(self, sender, updated):
        '''Event holder to update the MACD Rolling Window values'''
        if self.macd.IsReady:
            self.macdWindow.Add(updated)

    def RsiUpdated(self, sender, updated):
        '''Event holder to update the RSI Rolling Window values'''
        if self.rsi.IsReady:
            self.rsiWindow.Add(updated)
            
            
    def CloseUpdated(self, sender, bar):
        '''Event holder to update the close Rolling Window values'''
        self.closeWindow.Add(bar.Close)
       
    @property 
    def IsReady(self):
        return self.macd.IsReady and self.rsi.IsReady and self.closeWindow.IsReady     
       
  
from datetime import datetime,timedelta
SupportD = None
ResistanceD = None

class SupportResistance(ReversalAlpha):
    
    def __init__(self, algorithm):
        
        self.ticker = "USDCAD"
        self.Algorithm = algorithm
        self.SupportResistance = GetPriceLevels(self, series, variation = 0.005, h = 3)
        #find out how to consolidate hourly data into 4hr bars
        self.FourHourWindow = RollingWindow[float](7)
        algorithm.Consolidate(self.Ticker, timedelta(hours=4), self.SaveFourHourBars)
        
        
    def NextSupport(self):
        
        price = self.Algorithm.Securities[self.Ticker].Price
        
        SupportD, ResistanceD = self.SupportResistance
        
        less_than_price = [x for x in SupportD if x < price ]
        
        return less_than_price[min4(range(len(less_than_price)), key=lambda i: abs(less_than_price[i] - price))]
        
    
    def NextResistance(self):
        price = self.Algorithm.Securities[self.Ticker].Price
        
        SupportD, ResistanceD = self.SupportResistance
        
        greater_than_price = [y for y in ResistanceD if y > price ]
        
        return greater_than_price[min(range(len(greater_than_price)), key=lambda i: abs(greater_than_price[i] - price))]
        
    def SaveFourHourBars(self, bar):
        self.FourHourWindow.Add(bar)
        
    
# Your New Python File
#How do you conduct an inheritance of methods of a class from another .py file and create a new method using data from
# the inherited class. .
#Here's a rough idea of what i wanted to create:

""" Block of code whose output gives us daily support levels as well as resistance
levels """

from datetime import datetime,timedelta
import numpy as np

class DailySupport(QCAlgorithm):

    def Initialize(self):
        
     
        self.ticker = "USDCAD"
        # Rolling Windows to hold bar close data keyed by symbol
        self.closingData = {}
        #for ticker in tickers:
        symbol = self.AddForex(self.ticker, Resolution.Daily, Market.Oanda).Symbol
        self.closingData[symbol] = RollingWindow[float](50)
            # Warm up our rolling windows
        self.SetWarmUp(50)
        
    def OnData(self, data):
        
        for symbol, window in self.closingData.items():
            if data.ContainsKey(symbol) and data[symbol] is not None:
                window.Add(data[symbol].Close)
        
        if self.IsWarmingUp or not all([window.IsReady for window in self.closingData.values()]):
            return
        
        for symbol, window in self.closingData.items(): #references the key-value pairs in the dictionary
            supports_D, resistances_D = self.GetPriceLevels(window) # Daily Supports and Daily Resistances
            self.Log(f"Symbol: {symbol.Value} , Supports: {supports_D} , Resistances: {resistances_D}")
            
            
    def GetPriceLevels(self, series, variation = 0.005, h = 3):
        
        supports_D = [] # List that will hold daily Supports points
        resistances_D = [] # List that will hold daily Resistances points
        
        maxima = []
        minima = []
        
        # finding maxima and minima by looking for hills/troughs locally
        for i in range(h, series.Size-h):
            if series[i] > series[i-h] and series[i] > series[i+h]:
                maxima.append(series[i])
            elif series[i] < series[i-h] and series[i] < series[i+h]:
                minima.append(series[i])
       
        # identifying maximas which are resistances
        for m in maxima:
            r = m * variation
            # maxima which are near each other
            commonLevel = [x for x in maxima if x > m - r and x < m + r]
            # if 2 or more maxima are clustered near an area, it is a resistance
            if len(commonLevel) > 1:
                # we pick the highest maxima if the cluster as our resistance
                level = max(commonLevel)
                if level not in resistances_D:
                    resistances_D.append(level)
        
        # identify minima which are supports
        for l in minima:
            r = l * variation
            # minima which are near each other
            commonLevel = [x for x in minima if x > l - r and x < l + r]
            # if 2 or more minima are clustered near an area, it is a support
            if len(commonLevel) > 1:
                # We pick the lowest minima of the cluster as our support
                level = min(commonLevel)
                if level not in supports_D:
                    supports_D.append(level)
            
        
        return supports_D, resistances_D

# Your New Python File

#if nextSupportZone > current_price:
#return


""" Block of code whose two methods output gives us next support and next resistance  """

from datetime import datetime,timedelta
from levelsdaily import DailySupport
SupportD = None
ResistanceD = None

class SupportResistance(DailySupport):
    
    def __init__(self, algorithm):
        
        self.ticker = "USDCAD"
        self.Algorithm = algorithm
      
        self.SupportResistance = super().GetPriceLevels(series)
        #find out how to consolidate hourly data into 4hr bars
        self.FourHourWindow = RollingWindow[float](21)
        algorithm.Consolidate(self.Ticker, timedelta(hours=4), self.SaveFourHourBars)
        
        
    def NextSupport(self):
        
        price = self.Algorithm.Securities[self.Ticker].Price
        
        SupportD, ResistanceD = self.SupportResistance
        
        less_than_price = [x for x in SupportD if x < price ]
        
        return less_than_price[min4(range(len(less_than_price)), key=lambda i: abs(less_than_price[i] - price))]
        
    
    def NextResistance(self):
        price = self.Algorithm.Securities[self.Ticker].Price
        
        SupportD, ResistanceD = self.SupportResistance
        
        greater_than_price = [y for y in ResistanceD if y > price ]
        
        return greater_than_price[min(range(len(greater_than_price)), key=lambda i: abs(greater_than_price[i] - price))]
        
    def SaveFourHourBars(self, bar):
        self.FourHourWindow.Add(bar)
        
    
# Your New Python File
#How do you conduct an inheritance of methods of a class from another .py file and create a new method using data from
# the inherited class. .
#Here's a rough idea of what i wanted to create:



# Your New Python File