| Overall Statistics |
|
Total Orders 65 Average Win 10.03% Average Loss -3.59% Compounding Annual Return -19.225% Drawdown 45.300% Expectancy -0.130 Start Equity 20100000.0 End Equity 14830278.08 Net Profit -26.218% Sharpe Ratio -0.462 Sortino Ratio -0.578 Probabilistic Sharpe Ratio 5.354% Loss Rate 77% Win Rate 23% Profit-Loss Ratio 2.80 Alpha -0.557 Beta 0.282 Annual Standard Deviation 0.392 Annual Variance 0.154 Information Ratio -3.15 Tracking Error 0.481 Treynor Ratio -0.642 Total Fees $1200313.81 Estimated Strategy Capacity $40000000.00 Lowest Capacity Asset BTCUSDT 18N Portfolio Turnover 11.06% |
from AlgorithmImports import *
class VasukiAlgorithm(QCAlgorithm):
def initialize(self):
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
self.set_start_date(2023, 1, 1) # Set start date to January 5, 2020
self.set_end_date(datetime.now() - timedelta(7)) # Set end date to last week
# self.set_time_zone("Asia/Kolkata")
self._stop_loss = 0.05
self._target = 0.1
self.upper_period = 7
self.down_period = 3
self.is_invested = 0
self.set_cash("USDT", 20000000)
self.set_brokerage_model(BrokerageName.BINANCE, AccountType.MARGIN)
# self.set_brokerage_model(BrokerageName.GDAX, AccountType.CASH)
# Select resolution
resolution = Resolution.DAILY
self.symbol_ = self.add_crypto("BTCUSDT", resolution, leverage=1).symbol
# Set requested data resolution
self.universe_settings.resolution = resolution
#Set WarmUp for Indicators
# self.set_warm_up(60*24*8)
self.set_warm_up(8)
self.sma_close_up = SimpleMovingAverage(self.upper_period)
self.sma_close_up_ = []
self.sma_close_down = SimpleMovingAverage(self.down_period)
self.sma_close_down_ = []
self.sma_vol_up = SimpleMovingAverage(self.upper_period)
self.sma_vol_up_ = []
self.sma_vol_down = SimpleMovingAverage(self.down_period)
self.sma_vol_down_ = []
self.entry_price = None
self.trigger_vol_ratio = 0.1
self.trigger_price_ratio = 0.01
# self._consolidator = self.consolidate(self.symbol_, Resolution.HOUR, TickType.Trade, self.on_data_hour)
# def on_data_hour(self, bar):
# self.sma_close_up.update(bar.EndTime, bar.close)
# self.sma_close_down.update(bar.EndTime, bar.close)
# # bid_size = bar.last_bid_size
# # ask_size = bar.last_ask_size
# # volume = (bid_size + ask_size) // 2
# volume = bar.volume
# self.sma_vol_up.update(bar.EndTime, volume)
# self.sma_vol_down.update(bar.EndTime, volume)
# if self.is_warming_up:
# return
# # if not self.portfolio.invested:
# if self.is_invested == 0:
# close_price_ch_wrt_3 = bar.close - self.sma_close_down.current.value
# close_price_ratio = 0
# if self.sma_close_up.current.value != 0:
# close_price_ratio = close_price_ch_wrt_3 / self.sma_close_up.current.value
# vol_ch_wrt_3 = volume - self.sma_vol_down.current.value
# vol_ratio = 0
# if self.sma_vol_up.current.value != 0:
# vol_ratio = vol_ch_wrt_3 / self.sma_vol_up.current.value
# if (vol_ratio > 0.1) and (close_price_ratio > 0.005):
# # self.set_holdings(self.symbol_, 0.9)
# margin = self.portfolio.GetMarginRemaining(self.symbol_, OrderDirection.Buy)
# self.buy(self.symbol_, (margin / bar.close)*0.9)
# self.entry_price_dict[self.symbol_.Value] = bar.close
# self.is_invested = 1
# elif (vol_ratio > 0.1) and (close_price_ratio < -0.005):
# # self.set_holdings(self.symbol_, -0.9)
# margin = self.portfolio.GetMarginRemaining(self.symbol_, OrderDirection.SELL)
# self.sell(self.symbol_, (margin / bar.close)*0.9)
# self.entry_price_dict[self.symbol_.Value] = bar.close
# self.is_invested = -1
def on_data(self, data):
if data.ContainsKey(self.symbol_):
bar = data.bars.get(self.symbol_)
self.sma_close_up.update(bar.EndTime, bar.close)
self.sma_close_down.update(bar.EndTime, bar.close)
self.sma_close_up_.append(bar.close)
self.sma_close_down_.append(bar.close)
volume = bar.volume
self.sma_vol_up.update(bar.EndTime, volume)
self.sma_vol_down.update(bar.EndTime, volume)
self.sma_vol_up_.append(volume)
self.sma_vol_down_.append(volume)
if self.is_warming_up:
return
sma_close_down = sum(self.sma_close_down_[-self.down_period:]) / self.down_period
sma_close_up = sum(self.sma_close_down_[-self.upper_period:]) / self.upper_period
sma_vol_down = sum(self.sma_vol_down_[-self.down_period:]) / self.down_period
sma_vol_up = sum(self.sma_vol_up_[-self.upper_period:]) / self.upper_period
close_price_ch_wrt_3 = bar.close - sma_close_down
close_price_ratio = 0
if sma_close_up != 0:
close_price_ratio = round(close_price_ch_wrt_3 / sma_close_up, 5)
vol_ch_wrt_3 = abs(volume - sma_vol_down)
vol_ratio = 0
if sma_vol_up != 0:
vol_ratio = round(vol_ch_wrt_3 / sma_vol_up, 5)
self.Debug(f"{bar.Time} {bar.EndTime} {round(bar.close, 2)} price_sma {round(sma_close_up, 2)} {round(sma_close_down, 2)}, {close_price_ratio}, {round(bar.volume, 2)} vol_sma {round(sma_vol_up, 2)}, {round(sma_vol_down, 2)}, {vol_ratio}")
qty = round(self.portfolio[self.symbol_].AbsoluteQuantity, 6)
if self.is_invested != 0:
if self.is_invested == 1:
if (close_price_ratio < 0) and (bar.close < (self.entry_price * (1 - self._stop_loss))):
self.sell(self.symbol_, qty)
self.Debug(f"stoploss triggered : qty {round(self.portfolio[self.symbol_].AbsoluteQuantity, 6)} : price_ratio : {close_price_ratio} : entry & close price : {round(self.entry_price, 2)} Avg Price : {round(self.portfolio[self.symbol_].AveragePrice, 2)} {round(bar.close, 2)}, LastTradeProfit : {round(self.portfolio[self.symbol_].LastTradeProfit)}")
self.is_invested = 0
elif (bar.close > (self.entry_price * (1 + self._target))):
self.sell(self.symbol_, qty)
self.Debug(f"target achieved : qty {round(self.portfolio[self.symbol_].AbsoluteQuantity, 6)} : price_ratio : {close_price_ratio} : entry & close price : {round(self.entry_price, 2)} Avg Price : {round(self.portfolio[self.symbol_].AveragePrice, 2)} {round(bar.close, 2)}, LastTradeProfit : {round(self.portfolio[self.symbol_].LastTradeProfit)}")
self.is_invested = 0
else:
if (close_price_ratio > 0) and (bar.close > (self.entry_price * (1 + self._stop_loss))):
self.buy(self.symbol_, qty)
self.Debug(f"stoploss triggered : qty {round(self.portfolio[self.symbol_].AbsoluteQuantity, 6)} : price_ratio : {close_price_ratio} : entry & close price : {round(self.entry_price, 2)} Avg Price : {round(self.portfolio[self.symbol_].AveragePrice, 2)} {round(bar.close, 2)}, LastTradeProfit : {round(self.portfolio[self.symbol_].LastTradeProfit)}")
self.is_invested = 0
elif (bar.close < (self.entry_price * (1 - self._target))):
self.buy(self.symbol_, qty)
self.Debug(f"target achieved : qty {round(self.portfolio[self.symbol_].AbsoluteQuantity, 6)} : price_ratio : {close_price_ratio} : entry & close price : {round(self.entry_price, 2)} Avg Price : {round(self.portfolio[self.symbol_].AveragePrice, 2)} {round(bar.close, 2)}, LastTradeProfit : {round(self.portfolio[self.symbol_].LastTradeProfit)}")
self.is_invested = 0
else:
if (vol_ratio > self.trigger_vol_ratio) and (close_price_ratio > self.trigger_price_ratio):
# self.set_holdings(self.symbol_, 0.9)
margin = self.portfolio.GetMarginRemaining(self.symbol_, OrderDirection.Buy)
qty = round((margin / bar.close)*0.9, 8)
self.buy(self.symbol_, qty)
self.entry_price = bar.close
self.Debug(f"long qty {round(self.portfolio[self.symbol_].AbsoluteQuantity, 6)} : vol ratio : {vol_ratio} price_ratio : {close_price_ratio} : entry & close price : {round(self.entry_price, 2)} Avg Price : {round(self.portfolio[self.symbol_].AveragePrice, 2)} {round(bar.close, 2)}")
self.is_invested = 1
elif (vol_ratio > self.trigger_vol_ratio) and (close_price_ratio < -self.trigger_price_ratio):
# self.set_holdings(self.symbol_, -0.9)
margin = self.portfolio.GetMarginRemaining(self.symbol_, OrderDirection.SELL)
qty = round((margin / bar.close)*0.9, 8)
self.sell(self.symbol_, qty)
self.entry_price = bar.close
self.Debug(f"short qty {round(self.portfolio[self.symbol_].AbsoluteQuantity, 6)} : vol ratio : {vol_ratio} price_ratio : {close_price_ratio} : entry & close price : {round(self.entry_price, 2)} Avg Price : {round(self.portfolio[self.symbol_].AveragePrice, 2)} {round(bar.close, 2)}")
self.is_invested = -1