Overall Statistics |
Total Trades 25 Average Win 1.10% Average Loss -4.80% Compounding Annual Return 3.784% Drawdown 6.500% Expectancy 0.127 Net Profit 7.392% Sharpe Ratio 0.559 Probabilistic Sharpe Ratio 24.449% Loss Rate 8% Win Rate 92% Profit-Loss Ratio 0.23 Alpha 0.013 Beta 0.096 Annual Standard Deviation 0.058 Annual Variance 0.003 Information Ratio -0.776 Tracking Error 0.214 Treynor Ratio 0.337 Total Fees $0.00 Estimated Strategy Capacity $120000.00 Lowest Capacity Asset USDCAD 8G |
from datetime import datetime,timedelta import numpy as np #from dailyhours import * #from fourhr_support_resistance import * Macdlong = None class MeasuredApricot(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 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.stopLossLevel = -0.05 # stop loss percentage self.stopProfitLevel = 0.01# stop profit percentage #self.SupportResistance = SupportResistance(self, self.ticker) self.SetWarmUp(50, Resolution.Hour) #def MarketClose(self): #self.SupportResistance.Reset() 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 #nextSupportZone = #nextResistanceZone = #support = self.SupportResistance.NextSupport() #resistance = 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 * tolerance(1.01) #Below Resistance = current_price < closestResistanceZone * tolerance # 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:
from datetime import datetime,timedelta import numpy as np class ReversalAlpha(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
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](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