| Overall Statistics |
|
Total Trades 128 Average Win 43.74% Average Loss -4.67% Compounding Annual Return 81.908% Drawdown 83.600% Expectancy 1.755 Net Profit 732.817% Sharpe Ratio 1.333 Probabilistic Sharpe Ratio 46.398% Loss Rate 73% Win Rate 27% Profit-Loss Ratio 9.37 Alpha 0.579 Beta 0.873 Annual Standard Deviation 0.654 Annual Variance 0.427 Information Ratio 1.132 Tracking Error 0.473 Treynor Ratio 0.999 Total Fees $118108.51 Estimated Strategy Capacity $1400000.00 Lowest Capacity Asset BTCUSD 2MN |
#region imports
from AlgorithmImports import *
#endregion
class VerticalNadionShield(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 1, 1) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
self.leverage = 1
self.SetBrokerageModel(BrokerageName.FTX, AccountType.Margin)
self.AddRiskManagement(MaximumDrawdownPercentPerSecurity(0.05))
self.cryptos = ["ETHUSD", "BTCUSD"]
self.cryptoCombinedMomentum = {}
for crypto in self.cryptos:
self.AddCrypto(crypto, Resolution.Hour).Symbol
self.Securities[crypto].SetDataNormalizationMode(DataNormalizationMode.TotalReturn)
self.cryptoCombinedMomentum[crypto] = CombinedMomentum(self, crypto)
self.SetWarmUp(125)
def shiftAssets(self, target):
if not (self.Portfolio[target].Invested):
for symbol in self.Portfolio.Keys:
self.Liquidate(symbol)
if not self.Portfolio.Invested:
for symbol in self.Portfolio.Keys:
self.MarketOrder(symbol, self.CalculateOrderQuantity(symbol, 1 * self.leverage))
def getMonthLastTradingDay(self):
month_last_day = DateTime(self.Time.year, self.Time.month, DateTime.DaysInMonth(self.Time.year, self.Time.month))
tradingDays = self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, DateTime(self.Time.year, self.Time.month, 1), month_last_day)
tradingDays = [day.Date.date() for day in tradingDays]
return tradingDays[-1]
def OnData(self, data):
if self.IsWarmingUp:
return
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15,55,0), Action(self.Rebalance))
def Rebalance(self):
topEquities = sorted(self.cryptoCombinedMomentum.items(), key=lambda x: x[1].getValue(), reverse=True)
if (topEquities[0][1].getValue() > 0):
self.shiftAssets(topEquities[0][0])
#self.shiftAssets(topEquities[0][1])
else:
self.Liquidate()
class CombinedMomentum():
def __init__(self, algo, symbol):
self.fst = algo.MOMP(symbol, 30, Resolution.Daily)
#self.med = algo.MOMP(symbol, 90, Resolution.Daily)
#self.slw = algo.MOMP(symbol, 180, Resolution.Daily)
def getValue(self):
#value = (self.fst.Current.Value + self.med.Current.Value + self.slw.Current.Value) / 3
value = (self.fst.Current.Value)
return value