| Overall Statistics |
|
Total Trades 17 Average Win 1.89% Average Loss -1.15% Compounding Annual Return 3.878% Drawdown 23.200% Expectancy 0.978 Net Profit 4.998% Sharpe Ratio 0.257 Probabilistic Sharpe Ratio 15.398% Loss Rate 25% Win Rate 75% Profit-Loss Ratio 1.64 Alpha 0.009 Beta 0.267 Annual Standard Deviation 0.147 Annual Variance 0.022 Information Ratio -0.411 Tracking Error 0.17 Treynor Ratio 0.142 Total Fees $0.00 Estimated Strategy Capacity $1600000.00 Lowest Capacity Asset EOSUSD E3 |
#region imports
from AlgorithmImports import *
#endregion
class TrailingStopLoss(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 1, 1)
self.SetEndDate(2022, 8, 3)
self.SetCash(100000)
universe = ['BTCUSD', 'ETHUSD', 'XRPUSD', 'EOSUSD', 'LTCUSD']
self.pairs = [ Pair(self, ticker) for ticker in universe]
self.entryTicket = None
self.stopMarketTicket = None
self.highestPrice = 0
def OnData(self, data):
for pair in self.pairs:
# is rsi ready
if not pair.sma.IsReady and not pair.rsi.IsReady:
return
price = data[pair.symbol].Price
rsi = pair.rsi.Current.Value
sma = pair.sma.Current.Value
# send entry limit order
if rsi<25 and sma > price and not self.Portfolio[pair.symbol].Invested:
self.Debug("rsi is less than 25 and sma is greater than price")
quantity = self.CalculateOrderQuantity(pair.symbol, 0.2)
self.entryTicket = self.LimitOrder(pair.symbol, quantity, price, "Entry Order")
#trailing stop loss
if self.stopMarketTicket is not None and self.Portfolio[pair.symbol].Invested:
# move up trailing stop price
if price > self.highestPrice:
self.highestPrice = price
updateFields = UpdateOrderFields()
updateFields.StopPrice = price * 0.96
self.stopMarketTicket.Update(updateFields)
#self.Debug(updateFields.StopPrice)
def OnOrderEvent(self, orderEvent):
for pair in self.pairs:
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(pair.symbol, -self.entryTicket.QuantityFilled, 0.96 * self.entryTicket.AverageFillPrice)
# save fill time of stop loss order (and reset highestPrice)
if self.stopMarketTicket is not None and self.stopMarketTicket.OrderId == orderEvent.OrderId:
self.highestPrice = 0
class Pair:
def __init__(self, algorithm, ticker):
self.symbol = algorithm.AddCrypto(ticker,Resolution.Daily,Market.Bitfinex).Symbol
self.rsi = algorithm.RSI(self.symbol,14,MovingAverageType.Simple, Resolution.Daily)
self.sma = algorithm.SMA(self.symbol,50,Resolution.Daily)
def OnEndOfDay(self):
self.Plot("Indicators","RSI", pair.rsi.Current.Value)
self.Plot("Indicators","SMA", pair.sma.Current.Value)