Market sentiment is high when everyone is profit on paper, and vice versa. Can we use this as an indicator to trade?
While the long only follow version of this strategy performs great, the long-short version of it is not as good. Mainly due to the fact that short-selling adds extra risk to a position. Though you may gain on a bear market, but usually the short position will give away most return in the following bull market. A better modification is to increate the range of the weight, allowing close to full position when the rank is high, such that you still gain full access to a long bull market.
from btbox import *
from pandas import Series
SYMBOL = 'SPY'
START = '2000-01-01'
WINDOW = 504
INTERVAL = 5
dfs = {SYMBOL: import_yahoo_csv(f'../../_data_/{SYMBOL}_bar1day.csv')}
class BM_AllInAndForget(Strategy):
def initial(self, b: Broker):
b.portfolio.trade_target_weight(SYMBOL, 1)
class BM_KeepAtHalf(Strategy):
@interval(INTERVAL)
def step(self, b: Broker):
b.portfolio.trade_target_weight(SYMBOL, 0.5)
def pnl_ratio(win: Series) -> float:
pnlr = win.rank(pct=True)
return pnlr[-1]
def ST_LongShortPnL(min, max):
offset = max - min
class ST(Strategy):
name = f'ST_LongShortPnl_range[{min},{max}]'
@interval(INTERVAL)
def step(self, b: Broker):
win = b.market.get_close_window(SYMBOL)
pnlr = pnl_ratio(win)
weight = min + offset * pnlr
b.portfolio.trade_target_weight(SYMBOL, weight)
self.journal.mark(weight, 'weight')
return ST
bt = create_backtest(
[
BM_AllInAndForget,
BM_KeepAtHalf,
ST_LongShortPnL(0, 1),
ST_LongShortPnL(-0.2, 1),
ST_LongShortPnL(-0.2, 1.5),
ST_LongShortPnL(-0.5, 1.5),
],
dfs,
start=START,
window=WINDOW,
)
results = bt.run()
results.dashboard_pretty()
return | cagr | mu | sigma | mdd | duration | sharpe | calmar | |
---|---|---|---|---|---|---|---|---|
BM_AllInAndForget | 316.2% | 6.43% | 8.25% | 19.90% | -55.19% | 517 days 00:00 | 0.415 | 0.149 |
BM_KeepAtHalf | 125.8% | 3.63% | 4.07% | 9.90% | -31.49% | 517 days 00:00 | 0.411 | 0.129 |
ST_LongShortPnl_range[0,1] | 245.7% | 5.57% | 6.16% | 11.85% | -23.52% | 22 days 00:00 | 0.520 | 0.262 |
ST_LongShortPnl_range[-0.2,1] | 218.5% | 5.20% | 5.75% | 11.47% | -23.56% | 62 days 00:00 | 0.501 | 0.244 |
ST_LongShortPnl_range[-0.2,1.5] | 436.4% | 7.62% | 8.90% | 17.37% | -33.45% | 22 days 00:00 | 0.512 | 0.266 |
ST_LongShortPnl_range[-0.5,1.5] | 367.0% | 6.97% | 8.29% | 17.39% | -34.69% | 62 days 00:00 | 0.477 | 0.239 |
results.plot(log_y=True)
results['ST_LongShortPnl_range[-0.2,1.5]'].journals['weight'].ffill.plot_line_under_price(SYMBOL)