Overall Statistics |
Total Trades
63
Average Win
30.80%
Average Loss
-9.28%
Compounding Annual Return
59.860%
Drawdown
61.000%
Expectancy
0.881
Net Profit
2299.967%
Sharpe Ratio
1.518
Probabilistic Sharpe Ratio
91.282%
Loss Rate
56%
Win Rate
44%
Profit-Loss Ratio
3.32
Alpha
0.522
Beta
-0.011
Annual Standard Deviation
0.343
Annual Variance
0.118
Information Ratio
1.059
Tracking Error
0.367
Treynor Ratio
-46.456
Total Fees
$3264.13
|
# https://quantpedia.com/strategies/time-series-momentum-combined-with-volatility-filters-in-futures-markets/ # # The investment universe consists of stocks of firms whose fleet consists of tankers more than 66% (DHT Holding, Teekay, Tsakos # Energy Nav and Capital Product Partners). Nextly, consider a variable BT(t) that is the natural logarithm of the Baltic Tanker # Index at time t and two moving averages are employed: a six-week (long-term) moving average MA(6) and the lag of the relationship # (short-term) denoted as MA(1). When the short-term moving average exceeds the long-term moving average, it is considered as a buy # signal, because it suggests that prices are moving higher at a faster rate than in the past. On the other hand, when the short-term # moving average passes below the long-term moving average, it is considered as a sell signal. In-between the crossovers, strategy # dictates that investor continues to be in the market (for example after a buy signal the algorithm buys and holds until a sell signal is found). import fk_tools import numpy as np from collections import deque class Using_Baltic_Dry_Index_Tanker_Shipping_Companies(QCAlgorithm): def Initialize(self): self.SetStartDate(2013, 1, 1) self.SetEndDate(2019, 10, 1) self.SetCash(100000) self.symbol = 'BADI' data = self.AddData(QuantpediaEquity, self.symbol, Resolution.Daily) data.SetFeeModel(fk_tools.CustomFeeModel(self)) self.period = 6*5 self.SetWarmUp(self.period) self.sma_6 = self.SMA(self.symbol, self.period, Resolution.Daily) self.sma_1 = self.SMA(self.symbol, 5, Resolution.Daily) def OnData(self, data): if self.IsWarmingUp: return if self.sma_1.Current.Value > self.sma_6.Current.Value: if not self.Portfolio[self.symbol].IsLong: self.SetHoldings(self.symbol, 1) else: if not self.Portfolio[self.symbol].IsShort: self.SetHoldings(self.symbol, -1) # NOTE: IMPORTANT: Data order must be ascending (datewise) class QuantpediaEquity(PythonData): def GetSource(self, config, date, isLiveMode): return SubscriptionDataSource("data.quantpedia.com/backtesting_data/equity/{0}.csv".format(config.Symbol.Value), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv) def Reader(self, config, line, date, isLiveMode): data = QuantpediaEquity() data.Symbol = config.Symbol if not line[0].isdigit(): return None split = line.split(';') data.Time = datetime.strptime(split[0], "%m/%d/%Y") data['settle'] = float(split[1]) data.Value = float(split[1]) return data
import numpy as np from collections import deque def Return(values): return (values[-1] - values[0]) / values[0] def Volatility(values): values = np.array(values) returns = (values[1:] - values[:-1]) / values[:-1] return np.std(returns) # Custom fee model class CustomFeeModel(FeeModel): def GetOrderFee(self, parameters): fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005 return OrderFee(CashAmount(fee, "USD")) # Quantpedia data # NOTE: IMPORTANT: Data order must be ascending (datewise) class QuantpediaFutures(PythonData): def GetSource(self, config, date, isLiveMode): return SubscriptionDataSource("data.quantpedia.com/backtesting_data/futures/{0}.csv".format(config.Symbol.Value), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv) def Reader(self, config, line, date, isLiveMode): data = QuantpediaFutures() data.Symbol = config.Symbol if not line[0].isdigit(): return None split = line.split(';') data.Time = datetime.strptime(split[0], "%d.%m.%Y") + timedelta(days=1) data['settle'] = float(split[1]) data.Value = float(split[1]) return data