Overall Statistics |
Total Orders 3454 Average Win 0.89% Average Loss -0.78% Compounding Annual Return 28.888% Drawdown 30.500% Expectancy 0.198 Start Equity 100000.0 End Equity 1204086.73 Net Profit 1104.087% Sharpe Ratio 1.202 Sortino Ratio 0.985 Probabilistic Sharpe Ratio 77.684% Loss Rate 44% Win Rate 56% Profit-Loss Ratio 1.14 Alpha 0.182 Beta 0.026 Annual Standard Deviation 0.153 Annual Variance 0.024 Information Ratio 0.498 Tracking Error 0.21 Treynor Ratio 7.182 Total Fees $83086.22 Estimated Strategy Capacity $61000.00 Lowest Capacity Asset BTCUSD E3 Portfolio Turnover 96.18% |
# https://quantpedia.com/strategies/overnight-effect-during-high-volatility-days-in-bitcoin/ # # The investment universe consists of Bitcoin cryptocurrency. # Firstly, each day at 0.00 UTC, calculate the 30-day historical volatility of the BTC returns. Subsequently, determine the median of the historical volatility over one # year (365 days). Use this moving median value as the benchmark for categorizing the next 24-hour period as “High Volatility” (the 30-day historical volatility is above # the moving median) or “Low Volatility” (the 30-day historical volatility is above the moving median). # Finally, if the period is classified as “High Volatility” period, buy Bitcoin at 21:00 and sell it at 23:00. # region imports from AlgorithmImports import * import numpy as np from typing import List from pandas.core.frame import DataFrame # endregion class OvernightEffectduringHighVolatilityDaysinBitcoin(QCAlgorithm): def Initialize(self): self.SetStartDate(2015, 1, 1) self.SetCash(100000) self.volatility_period:int = 30 * 24 self.history_period:int = 365 self.warmup_period:int = self.history_period * 24 self.btc:Symbol = self.AddCrypto('BTCUSD', Resolution.Hour, Market.Bitfinex).Symbol self.Securities[self.btc].SetFeeModel(CustomFeeModel()) self.calculation_hour:int = 0 # calculation at 00:00 self.traded_window:List[int] = [21, 23] # trading from 21:00 to 23:00 self.trade_flag:bool = False self.settings.daily_precise_end_time = False self.settings.minimum_order_margin_portfolio_percentage = 0. self.btc_volatility:RollingWindow = RollingWindow[float](self.history_period) self.SetWarmup(self.warmup_period, Resolution.Hour) def OnData(self, data: Slice) -> None: if self.UtcTime.hour == self.calculation_hour: monthly_volatility:float = self.History(self.btc, self.volatility_period, Resolution.Hour).close.unstack(level=0).pct_change().std().values[0] self.btc_volatility.Add(monthly_volatility) if self.IsWarmingUp: return if not self.btc_volatility.IsReady: return if self.btc_volatility[0] > np.median(list(self.btc_volatility)[1:]): self.trade_flag = True # trade execution if self.UtcTime.hour == self.traded_window[0]: if not self.trade_flag: return self.trade_flag = False if self.btc in data and data[self.btc]: self.SetHoldings(self.btc, 1) if self.UtcTime.hour == self.traded_window[1] and self.Portfolio[self.btc].Invested: self.Liquidate() # custom fee model class CustomFeeModel(FeeModel): def GetOrderFee(self, parameters): fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005 return OrderFee(CashAmount(fee, "USD"))