| 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