| Overall Statistics |
|
Total Trades 37 Average Win 0.27% Average Loss -1.07% Compounding Annual Return 4.860% Drawdown 28.800% Expectancy -0.896 Net Profit 6.271% Sharpe Ratio 0.267 Probabilistic Sharpe Ratio 15.793% Loss Rate 92% Win Rate 8% Profit-Loss Ratio 0.25 Alpha -0.003 Beta 0.664 Annual Standard Deviation 0.267 Annual Variance 0.071 Information Ratio -0.157 Tracking Error 0.257 Treynor Ratio 0.107 Total Fees $0.00 Estimated Strategy Capacity $10000000.00 Lowest Capacity Asset EOSUSD XJ |
#region imports
from AlgorithmImports import *
#endregion
# Cryptos RSI and SMA with Stop Loss
# ------------------------------------------------------------------------------------------
CRYPTOS = ['BTCUSD', 'ETHUSD', 'EOSUSD', 'LTCUSD','XRPUSD']; MA = 50; RSI = 14; SL = 0.04;
# ------------------------------------------------------------------------------------------
class CryptosRSIandSMA(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 1, 1)
self.SetCash(100000)
self.stopMarketTicket = None
self.entryTicket = None
self.cryptos = [self.AddCrypto(ticker, Resolution.Daily).Symbol for ticker in CRYPTOS]
self.sma = {}; self.rsi = {}; self.enter_price={}; self.highestPrice={};
for sec in self.cryptos:
self.sma[sec] = self.SMA(sec, MA, Resolution.Daily)
self.rsi[sec] = self.RSI(sec, RSI, MovingAverageType.Simple, Resolution.Daily)
self.enter_price[sec] = 0
self.highestPrice[sec] = 0
self.SetWarmUp(max(MA, RSI), Resolution.Daily)
def OnData(self, data):
if self.IsWarmingUp: return
for sec in self.cryptos:
if not self.sma[sec].IsReady or not self.rsi[sec].IsReady: continue
rsi = self.rsi[sec].Current.Value
price = self.Securities[sec].Price
sma = self.sma[sec].Current.Value
quantity = self.CalculateOrderQuantity(sec, 0.19)
pnl = self.Securities[sec].Holdings.UnrealizedProfitPercent
if not self.Portfolio[sec].Invested:
if rsi <25 and sma > price:
self.entryTicket = self.LimitOrder(sec, quantity, price, "entry order")
self.enter_price[sec] = price
elif self.Portfolio[sec].Invested and self.stopMarketTicket is not None:
if self.enter_price[sec] > self.highestPrice[sec]:
self.highestPrice[sec] = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price * 0.96
self.stopMarketTicket.Update(updateFields)
self.Debug(updateFields.StopPrice)
def OnOrderEvent(self, orderEvent):
for sec in self.cryptos:
if orderEvent.Status != OrderStatus.Filled:
return
# send stop loss order if entry limit order is filled
if self.entryTicket is not None and self.entryTicket.OrderId == orderEvent.OrderId:
self.stopMarketTicket = self.StopMarketOrder(sec, -self.entryTicket.QuantityFilled, 0.96 * self.enter_price[sec])
# save fill time of stop loss order (and reset highestPrice)
if self.stopMarketTicket is not None and self.stopMarketTicket.OrderId == orderEvent.OrderId:
self.highestPrice[sec] = 0
self.enter_price[sec]=0
def OnEndOfDay(self, symbol):
if self.IsWarmingUp: return
for sec in self.cryptos:
if not self.sma[sec].IsReady or not self.rsi[sec].IsReady: continue
self.Plot("RSI", sec, self.rsi[sec].Current.Value)
self.Plot("RSI", 'threshold', 25)
self.Plot("SMA", sec, self.sma[sec].Current.Value)