Prototyping and backtesting trading strategies naively (in python) with descriptive plots

The fastest way to test the profitability of a trading model generating signals is to do a simple backtest (which means no hindsight biases i.e at least 1 period of timeframe lag from signal even if you timeframe is in milliseconds) using historical time series.

actual returns = absolute return (no hindsight biases to signal) – transaction cost – spillage

Spillage really matters when the trade model is tested on live markets. Examples are when the spread widens on entry such that without the median price moving, the opposite bid or ask (if long or short) hits the stop loss.

Toolbox:

Data from Quandl – free registration and simply use their API token in python https://www.quandl.com/

pandas – good for munging (merging and creating new derived  timeseries) and plotting time series, where support of datetime goes to milliseconds

seaborn – for more advanced plots such as conditional regression as well as segmented correlation or scattered plots

numpy – mention here since its very good for mathematical expressions with its vectorisation capabilities. It performs fast because numpy is coded in C and Fortan.

Work done in Spyder, a python interface

Plot of key macro variables where prices changes signal a change in the economic demand and supply

p1

Source: Quandl, Python

p2Source: Quandl, Python

Conditional regression subplots with seaborn

Noticeable changes in slope of regression (sensitivity) when conditioned on VIX being above 90% percentile (classified as “fear” regime), vice versa. Returns rather than level values are used i.e. Slope is row Beta against column as determinant. Weakness here is that outliers presence causes the slope to be skewed widely for some subplots.

Common trends…

  • SPX and VIX are really negative correlated, but less so if market is already in a fear

When market is fearful…

  • DXY and near yield becomes less positively correlated
  • SPX and near yield raises more to a rise in crude oil price (signs of inflation)
  • SPX raises more to a fall in near bond prices (equities-bond rotation)
  • gold becomes a safe heaven or “a hedging tool to equities bear” and switches to positive correlation with fear index
  • DXY fall and rise becomes more contained as risk off sentiment slows down speculative capital flow

p3.png

Source: Quandl, Python

Backtest Results
#=========================================================================
# strategy 1 – long SPX when VIX below 75% percentile of a long history
#=========================================================================

Strategy performs -105.351% over buy-and-holdIn

p4

#=========================================================================
# strategy 2 – long SPX when USSG2YR above 3 months simple average
#=========================================================================

Strategy performs -143.764% over buy-and-hold

p5

 

#=========================================================================
# strategy 3 – long DXY when USSG2YR above 1 month simple average
#=========================================================================

Strategy performs -66.034% over buy-and-hold

p6

 

#=========================================================================
# strategy 4 – long SPX when XAU below 1 month simple average
#=========================================================================

Strategy performs -48.412% over buy-and-hold

97

5 Replies to “Prototyping and backtesting trading strategies naively (in python) with descriptive plots”

  1. mydata[‘Regime’] = np.where(mydata[‘CBOE/VIX – VIX Close’] &gt= fear_idx, “fear”, “calm”)
    ^
    SyntaxError: invalid syntax

    I cannot fix this error. Can you help please?

    Like

      1. For some reason, line #35 looks like this:

        mydata[‘Regime’] = np.where(mydata[‘CBOE/VIX – VIX Close’] >= fear_idx, “fear”, “calm”)
        mydata[‘Regime’].value_counts()

        The same problem appear also in lines #63, #83 and #103. Maybe an issue of WordPress

        I replace “>” with “>” and the code I think now runs ok.

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s