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