Using Baltic Dry Index to Trade Tanker Shipping Companies
Log in to collectAcademic paper
A Cointegrating Stock Trading Strategy for Tanker Shipping Companies
Nektarios Michail; Konstantinos D. Melas
- CYCyprus University of Technology
- GRMetropolitan College
- GRUniversity of Western Macedonia
- ?Metropolitan College, Greece - Faculty of Business and Economics
Strategy in a nutshell
Trades tanker-dominant stocks using the Baltic Tanker Index with a moving-average crossover: buys when the one-week lagged MA(1) exceeds the six-week MA(6) and sells when it falls below. Positions are held between signals to capture price momentum.
Economic rationale
Shipping stock returns are closely linked to global freight rates rather than local market risks. The Baltic Tanker Index’s cointegration with tanker stocks enables systematic momentum trading that outperforms buy-and-hold approaches.
Backtest performance
Annualised return3.86%
Beta-0.008
Win rate46%
Full Python code
from AlgorithmImports import *
#endregion
class UsingBalticDryIndexTankerShippingCompanies(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 1, 1)
self.SetCash(100000)
data = self.AddData(QuantpediaEquity, 'BADI', Resolution.Daily)
data.SetFeeModel(CustomFeeModel())
self.symbol = data.Symbol
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_6.IsReady and self.sma_1.IsReady:
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/index/BADI.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
# Custom fee model
class CustomFeeModel(FeeModel):
def GetOrderFee(self, parameters):
fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
return OrderFee(CashAmount(fee, "USD"))