import pandas as pd
from moonshot import Moonshot
from moonshot.commission import PerShareCommission
class USStockCommission(PerShareCommission):
BROKER_COMMISSION_PER_SHARE = 0.005
class VMOTTrend(Moonshot):
"""
Hedging strategy that sells the market based on 2 trend rules:
1. Sell 50% if market price is below 12-month moving average
2. Sell 50% if market 12-month return is below 0
This strategy constitutes the "Trend" portion of the Alpha Architect
Value/Momentum/Trend (VMOT) ETF.
"""
CODE = "vmot-trend"
DB = "sharadar-us-etf-1d"
SIDS = "FIBBG000BDTBL9"
REBALANCE_INTERVAL = "W"
COMMISSION_CLASS = USStockCommission
def prices_to_signals(self, prices: pd.DataFrame):
closes = prices.loc["Close"]
one_year_returns = (closes - closes.shift(252))/closes.shift(252)
market_below_zero = one_year_returns < 0
mavgs = closes.rolling(window=252).mean()
market_below_mavg = closes < mavgs
hedge_signals = market_below_zero.astype(int) + market_below_mavg.astype(int)
hedge_signals = -hedge_signals
return hedge_signals
def signals_to_target_weights(self, signals: pd.DataFrame, prices: pd.DataFrame):
signals = signals.resample(self.REBALANCE_INTERVAL).last()
signals = signals.reindex(prices.loc["Close"].index, method="ffill")
weights = signals / 2
return weights
def target_weights_to_positions(self, weights: pd.DataFrame, prices: pd.DataFrame):
return weights.shift()
def positions_to_gross_returns(self, positions: pd.DataFrame, prices: pd.DataFrame):
closes = prices.loc["Close"]
gross_returns = closes.pct_change() * positions.shift()
return gross_returns
def order_stubs_to_orders(self, orders: pd.DataFrame, prices: pd.DataFrame):
orders["Exchange"] = "SMART"
orders["OrderType"] = "MOC"
orders["Tif"] = "DAY"
return orders