Difference between revisions of "Pair Trading Models"
(→Kalman-grid Model (v2)) |
(→Kalman-grid Model (v2)) |
||
(7 intermediate revisions by one user not shown) | |||
Line 165: | Line 165: | ||
* auxiliary standard deviation period - if equal to zero, Kalman filter is used to estimate standard deviation, if non-zero, auxiliary standard deviation indicator with this period is used (an the estimate from Kalman filter is ignored) | * auxiliary standard deviation period - if equal to zero, Kalman filter is used to estimate standard deviation, if non-zero, auxiliary standard deviation indicator with this period is used (an the estimate from Kalman filter is ignored) | ||
* unstable period = how many Kalman filter observations are ignored at the beginning (first observations are quite unstable) | * unstable period = how many Kalman filter observations are ignored at the beginning (first observations are quite unstable) | ||
− | * entry threshold E<sub>n</sub> for Z-score, typical value range is <1 | + | * entry threshold E<sub>n</sub> for Z-score, typical value range is <1, 2> |
− | * exit threshold E<sub>x</sub> for Z-score, typical value is <- | + | * exit threshold E<sub>x</sub> for Z-score, typical value is <-1, 0>...negative values allowed (allows to exit at other side) |
* downtick threshold E<sub>d</sub> for Z-score, typical value is <0, 1>...used for downtick mode only as a third band | * downtick threshold E<sub>d</sub> for Z-score, typical value is <0, 1>...used for downtick mode only as a third band | ||
* max Z-score E<sub>max</sub> (optional, to filter out extremes, typical value is >10 if used) | * max Z-score E<sub>max</sub> (optional, to filter out extremes, typical value is >10 if used) | ||
Line 198: | Line 198: | ||
* the simple A.I. inside is profit-based - so not-so-good pairs with waves in profit can "fool" the algorithm so it falls from the optimum | * the simple A.I. inside is profit-based - so not-so-good pairs with waves in profit can "fool" the algorithm so it falls from the optimum | ||
* model performance is proportional to margin usage | * model performance is proportional to margin usage | ||
+ | * evaluating this model needs a lot of memory and processing resources | ||
Specialties: | Specialties: | ||
* if you set entry threshold to 1, exit threshold to -1, model to "simple" and if you allow reversals, the model will be "always-in-position" squeezing the most profit from good pairs | * if you set entry threshold to 1, exit threshold to -1, model to "simple" and if you allow reversals, the model will be "always-in-position" squeezing the most profit from good pairs | ||
− | To give some insight on performance: we took 300 best performing pairs from PTL database in period Jan 2013 - Jan 2016. Then we backtested all 300 pairs using '''out-of-sample''' period (Jan 2016 - Sep 2016) and we compared their performance. Models used: Ratio(per 14), Residual(20), Kalman Grid v1, Kalman Grid v2 using exit threshold of | + | To give some insight on performance: we took 300 best performing pairs from PTL database in period Jan 2013 - Jan 2016. Then we backtested all 300 pairs using '''out-of-sample''' period (Jan 2016 - Sep 2016) and we compared their performance. Models used: Ratio(per 14), Residual(20), Kalman Grid v1, Kalman Grid v2 using exit threshold of 0 (normal) and -1 (aggressive). Margin 50% (Req-T). Results here: |
{| | {| | ||
|'''Model''' | |'''Model''' | ||
Line 231: | Line 232: | ||
=== Model Support === | === Model Support === | ||
− | |||
* in PTL backtester: '''yes''' | * in PTL backtester: '''yes''' | ||
* in PTL portfolio backtester: '''yes''' | * in PTL portfolio backtester: '''yes''' | ||
− | * in PTL Trader: ''' | + | * in PTL Trader: '''since v1.4.0''' |
=== Model Parameters === | === Model Parameters === | ||
Line 250: | Line 250: | ||
== Kalman-Auto Model == | == Kalman-Auto Model == | ||
− | ''' | + | This model is very similar to Kalman-grid model, it is like his younger brother. The main difference is that the simple A.I. of this model is not trying to work with profit (which is problem with certain kind of pairs). Instead, it justs tries to find optimum δ (transition covariance) of the Kalman filter together with the entry threshold to match the '''margin usage target'''. An example: you can set this model to try to optimize everything so the strategy spends 50% time in position (so if you traded one year, the model spent only half a year in positions). Or you can say the average slot usage (margin usage) is 50%. This is useful for trading whole portfolios of Kalman-Auto based strategies, so you can fine tune the diversification inside the portfolio correctly. |
− | + | Advantages of this model: | |
+ | * the only parameter to fine-tune of this model is (apart from the usage target) V<sub>e</sub> (Kalman filter observation covariance), which is luckily not sensitive | ||
+ | * the model is much faster to evaluate than Kalman-Grid | ||
+ | * the simple A.I. of this model is robust and not-so easy to fool | ||
+ | * entry threshold is side-product of the self-optimization! | ||
+ | |||
+ | This is the model you need if you don't want to spent hours of optimizing parameters. You just tell it to trade and stay in position 60% of the time and that's it. On the other hands, it does not match in profits with Kalman-Grid for very good pairs (but actually it has similar performance when you divide the profit to the margin usage). | ||
+ | |||
+ | Please note there is no regulation feedback loop inside, the self optimization works just with ring-buffer with follows the current point and it is used for finding best parameters. So do not expect you set the target to 80% and at the end you get 80% portfolio usage. The good working range is <40, 60>. | ||
+ | |||
+ | Example: [https://www.pairtradinglab.com/backtests/WCGoZyG8rDVDQnY1 Visa/Mastercard backtest] with Usage Target set to 60%. Notice the '''% Days In Trade''' resulted in 64.9%. | ||
=== Model Support === | === Model Support === | ||
− | |||
* in PTL backtester: '''yes''' | * in PTL backtester: '''yes''' | ||
− | * in PTL portfolio backtester: ''' | + | * in PTL portfolio backtester: '''yes''' |
− | * in PTL Trader: ''' | + | * in PTL Trader: '''since v1.4.0''' |
=== Model Neutrality === | === Model Neutrality === | ||
Line 265: | Line 274: | ||
=== Model Parameters === | === Model Parameters === | ||
* Kalman filter observation covariance V<sub>e</sub>, typical value is 0.001 | * Kalman filter observation covariance V<sub>e</sub>, typical value is 0.001 | ||
− | * | + | * desired margin usage threshold in %, allowed range <20, 80>, the range <40,60> works the best in terms of how precise is the margin usage matched to the target |
+ | |||
+ | === Entering & Exiting Positions === | ||
+ | Same as in Residual Model, but: | ||
+ | * entry threshold is figured automatically by the model | ||
+ | * exit threshold is always 0 | ||
+ | * entry mode is always "simple" | ||
= Deprecated Models = | = Deprecated Models = | ||
* Orthogonal Model | * Orthogonal Model | ||
* Kalman-grid Model (v1) | * Kalman-grid Model (v1) |
Latest revision as of 11:09, 20 July 2022
Pair Trading Lab offers pair trading algorithms based on various mathematical models. These are models currently supported in PTL:
Contents |
[edit] Ratio Model
This is one of the standard pair trading models described in literature. It is based in ratio of instrument prices, moving average and standard deviation. In other words, it is based on Bollinger Bands indicator.
Since Nov 27th 2014, this model also supports additional RSI filter you can use in addition to Bollinger Bands method.
[edit] Model Support
- in PTL backtester: yes (max Z-score not supported)
- in PTL portfolio backtester: yes
- in PTL Trader: yes (RSI supported since v1.2.0)
[edit] Model Neutrality
We currently support only dollar-neutral version of this model, which means we allocate same amounts of margin to both legs based on current prices at the time of opening the position.
[edit] Model Parameters
- entry threshold E_{n} for Z-score, typical value range is <1.5, 2.5>, 2.0 is used most often
- exit threshold E_{x} for Z-score, typical value is <-0.5, 0.5>, 0 is used most often...negative values are allowed (to exit on other side)
- downtick threshold E_{d} for Z-score, typical values is <0, 1>, 0 is used most often...only used for downtick entry mode as a third band
- max Z-score E_{max} (optional, to filter out extremes, typical value is >4 if used)
- moving average period P_{m} (typical range <10, 100>), default = 15
- moving average type T (algorithm), default = exponential
- standard deviation period P_{s} (typical range <10, 100>), default = 15
- entry mode (simple, uptick, downtick)
- RSI period and threshold (optional RSI filtering)
[edit] Description
- we trade pair of stocks A, B, having price series A(t), B(t)
- we need to calculate ratio time series R(t) = A(t) / B(t)
- let's apply moving average of type T with period P_{m} on R(t) to get time series M(t)
- let's apply standard deviation with period P_{s} on R(t) to get time series S(t)
- now we can create Z-score series Z(t) as Z(t) = (R(t) - M(t)) / S(t), this time series can give us z-score to signal trading decision directly (in reality we have two Z-scores: Z-score_{ask} and Z-score_{bid} as they are calculated using different prices, but for the sake of simplicity let's now pretend we don't pay bid-ask spread and we have just one Z-score)
- another common approach (to visualize) is to create bands and put it above the moving average M(t):
- upper entry band U_{n}(t) = M(t) + S(t) * E_{n}
- lower entry band L_{n}(t) = M(t) - S(t) * E_{n}
- upper exit band U_{x}(t) = M(t) + S(t) * E_{x}
- lower exit band L_{x}(t) = M(t) - S(t) * E_{x}
- upper downtick band U_{d}(t) = M(t) + S(t) * E_{d} (applies to downtick entry mode only)
- lower downtick band L_{d}(t) = M(t) - S(t) * E_{d} (applies to downtick entry mode only)
- these bands are actually the same bands as in Bollinger Bands indicator and we can use crossing of R(t) and bands as trade signals
[edit] Entering Position
There are certain possible approaches how to interpret model statistics in order to make trading decisions. For entering position, we used to call them entry modes. This is the list of them and description how they work:
- entry mode = simple:
- to open short pair position, it is simple enough if the Z-score Z(t) >= E_{n} (equivalent to R(t) >= U_{n}(t))
- to open long pair position, it is simple enough if the Z-score Z(t) <= -E_{n} (equivalent to R(t) <= L_{n}(t))
- entry mode = uptick: same as simple, but in addition, previous Z-score must be below the entry band (so we cross the band from inside to outside):
- to open short pair position, we require Z(t) >= E_{n} (equivalent to R(t) >= U_{n}(t)) and Z(t-1) < E_{n} (same as R(t-1) < U_{n}(t-1))
- to open long pair position, we require Z(t) <= -E_{n} (equivalent to R(t) <= L_{n}(t)) and Z(t-1) > -E_{n} (same as R(t-1) > L_{n}(t-1))
- entry mode = downtick: we wait for the Z-score crossing back the band from outside to inside (but it must stay above the downtick band):
- to open short pair position, we require Z(t) < E_{n} and Z(t-1) >= E_{n} and Z(t) > E_{d}
- when using bands, it is the same as having R(t) < U_{n}(t) and R(t-1) >= U_{n}(t-1) and R(t) > U_{d}(t)
- to open long pair position, we require Z(t) > -E_{n} and Z(t-1) <= -E_{n} and Z(t) < -E_{d}
- when using bands, it is the same as having R(t) > L_{n}(t) and R(t-1) <= L_{n}(t-1) and R(t) < L_{d}(t)
Why do we have the simple entry mode? In normal situations and backtests, it gives same results as the uptick mode. But the difference comes up while trading multiple pairs in portfolio. The simple mode allows you to jump in the position immediately after a new slot is freed, regardless of the previous Z-scores.
Which entry mode is better? Hard to tell, sometimes the uptick, sometimes the downtick. You have to do your homework and decide, which idea suits your trading style better. In general, uptick/simple mode is more aggressive, as it does not wait for first signs of spread mean reversion.
[edit] Exiting Position
For exiting position, we always use only these simple rules:
- we exit short position when Z(t) <= E_{x} (equivalent to R(t) <= U_{x}(t))
- we exit long position when Z(t) >= -E_{x} (equivalent to R(t) >= L_{x}(t))
[edit] Moving Average Types
You can choose from these moving average algorithms:
- Simple Moving Average (SMA)
- Exponential Moving Average (EMA)
- Weighted Moving Average (WMA)
- Double Exponential Moving Average (DEMA)
- Triple Exponential Moving Average (TEMA)
- Triangular Moving Average (TMA)
- Kaufman Adaptive Moving Average (KAMA)
- MESA Adaptive Moving Average (MAMA)
- Triple Exponential T3 Moving Average
Which one is the best? It depends, you have to test for yourself. They mostly differ in the term of memory and how fast they react to changes. Industry standard and the default is EMA. We suggest to try all of them on some sample pair to see how they work.
[edit] RSI Filtering
You can combine the Z-score/Bollinger Band model with RSI indicator applied on the ratio R(t). RSI filter will be automatically enabled if you set RSI threshold to other value than zero. RSI filter is combined with the Z-score rules using AND operator (both entry rule and RSI entry rule must be true to open a position).
You can also change the RSI period if you want (default period = 15).
RSI Threshold is value between 0 and 50. Because RSI indicator value oscillates between 0 and 100 (where 50 = mean), your threshold value is just used to set real thresholds for RSI:
- let's assume RSI Period P_{r} was entered
- effective RSI value threshold is then 50+P_{r} (upper) and 50-P_{r} (lower)
- you can see both thresholds in the example image at the right side
Example:
- RSI Threshold entered is 15
- then, short positions are only opened, if RSI >= 65 (50+15)
- long positions are only opened, if RSI <=35 (50-15)
Useful hint: if you want to control entry rules just by RSI, you can set Entry Mode to simple and Entry Threshold to some low value.
[edit] Residual Model
Residual mode is based on linear regression. In literature it has been also referred to as the cointegration approach. Linear regression of both stocks is constructed in order to fit a linear relationship between both instruments and estimate its best parameters using the OLS method (Ordinary Least Squares). Then, standard deviation is applied on the regression residuals to estimate its statistical properties and calculate Z-scores.
This particular implementation is very simple. The regression is constructed using floating window of a fixed period, the same period is used for calculating the standard deviation.
[edit] Model Support
- in PTL backtester: yes (max Z-score not supported)
- in PTL portfolio backtester: yes
- in PTL Trader: yes (uptick and downtick modes are supported since v1.2.0)
[edit] Model Neutrality
We currently support only dollar-neutral version of this model, which means we allocate same amounts of margin to both legs based on current prices at the time of opening the position.
[edit] Model Parameters
- entry threshold E_{n} for Z-score, typical value range is <1.2, 2.5>, 1.5 is used most often
- exit threshold E_{x} for Z-score, typical value is <-0.5, 0.5>, 0 is used most often...negative values allowed (allows to exit at other side)
- downtick threshold E_{d} for Z-score, typical value is <0, 1>...used for downtick mode only as a third band
- max Z-score E_{max} (optional, to filter out extremes, typical value is >4 if used)
- linear regression period P (floating window is used), typical range <15, 300>
- entry mode (simple, uptick, downtick)
[edit] Description
- we trade pair of stocks A, B, having price series A(t), B(t)
- first we need to construct a linear regression between A(t), B(t) using OLS, where A(t) = β * B(t) + α + R(t)
- because we use floating window of period P (we calculate new regression each day), we actually get new series β(t), α(t), R(t), where β(t), α(t) are series of regression coefficients and R(t) are residuals (prediction errors)
- R(t) = A(t) - (β(t) * B(t) + α(t))
- then we apply standard deviation of period P on residuals R(t) and we put it to S(t)
- now we can create Z-score series Z(t) as Z(t) = R(t) / S(t), this time series can give us z-score to signal trading decision directly (in reality we have two Z-scores: Z-score_{ask} and Z-score_{bid} as they are calculated using different prices, but for the sake of simplicity let's now pretend we don't pay bid-ask spread and we have just one Z-score)
[edit] Entering Position
There are certain possible approaches how to interpret model statistics in order to make trading decisions. For entering position, we used to call them entry modes. This is the list of them and description how they work:
- entry mode = simple:
- to open short pair position, it is simple enough if the Z-score Z(t) >= E_{n}
- to open long pair position, it is simple enough if the Z-score Z(t) <= -E_{n}
- entry mode = uptick: same as simple, but in addition, previous Z-score must be below the entry band (so we cross the band from inside to outside):
- to open short pair position, we require Z(t) >= E_{n} and Z(t-1) < E_{n}
- to open long pair position, we require Z(t) <= -E_{n} and Z(t-1) > -E_{n}
- entry mode = downtick: we wait for the Z-score crossing back the band from outside to inside (while we must stay above the downtick band):
- to open short pair position, we require Z(t) < E_{n} and Z(t-1) >= E_{n} and Z(t) > E_{d}
- to open long pair position, we require Z(t) > -E_{n} and Z(t-1) <= -E_{n} and Z(t) < -E_{d}
[edit] Exiting Position
For exiting position, we always use only these simple rules:
- we exit short position when Z(t) <= E_{x}
- we exit long position when Z(t) >= -E_{x}
[edit] Kalman Model
This model is based on Kalman Filter. In this case, the filter is used here instead of linear regression to determine proper hedge ratio, deviation from the mean and the standard deviation of the spread. The advantage is that this filter is superior when dealing with noise compared to OLS or TLS methods, also it does not have any lookback period to optimize. The disadvantage is that is has another parameters (like δ) to find out.
We strongly recommend to read more details about Kalman filter applications in pair trading in this book.
While Kalman Filter also estimates the standard deviation on the fly, our implementation also supports a possibility of having an auxiliary standard deviation indicator applied directly on the forecast error time series. The advantage is that you get less sensitivity on the δ parameter, but on the other hand a new lookback parameter is introduced.
Kalman Model has too sensitive parameters which prevents it to be traded in reality. This model is provided only for education purposes - to be able to see how parameters affects its performance. Use Kalman Grid model for any serious trading.
[edit] Model Support
- in PTL backtester: yes (max Z-score not supported)
- in PTL portfolio backtester: not planned
- in PTL Trader: not planned
[edit] Model Neutrality
For Kalman Model, we support both dollar neutral (equal dollar amount invested to each leg) and beta neutral regimes.
[edit] Model Parameters
- Kalman filter transition covariance δ, typical value is 0.0001 - unfortunately this model is very sensitive to this parameter especially when using standard deviation estimate coming from the Kalman filter itself
- Kalman filter observation covariance V_{e}, typical value is 0.001
- auxiliary standard deviation period - if equal to zero, Kalman filter is used to estimate standard deviation, if non-zero, auxiliary standard deviation indicator with this period is used (an the estimate from Kalman filter is ignored)
- unstable period = how many Kalman filter observations are ignored at the beginning (first observations are quite unstable)
- entry threshold E_{n} for Z-score, typical value range is <1, 2>
- exit threshold E_{x} for Z-score, typical value is <-1, 0>...negative values allowed (allows to exit at other side)
- downtick threshold E_{d} for Z-score, typical value is <0, 1>...used for downtick mode only as a third band
- max Z-score E_{max} (optional, to filter out extremes, typical value is >10 if used)
- entry mode (simple, uptick, downtick)
[edit] Entering & Exiting Positions
Same as in Residual Model.
This model is provided for education purposes only.
[edit] Kalman-grid Model (v2)
After one year of experience with the Kalman-grid Model (v1) and researching machine learning principles, we have spent weeks of additional work on developing new version of Kalman Grid model, redesigned from scratch. Kalman Grid v2 is now the most advanced model PTL offers.
This model brings the superior performance of Kalman filter design, but it also deals with all the flaws of Kalman and old Kalman Grid v1:
- all parameters of Kalman filter have been eliminated (δ, V_{e}) - they are auto-estimated by the grid logic and updated with each price sample
- increased average performance compared to v1
- fixed issues of old version which prevented model to trade too often (biggest flaw of v1)
This model rendered the version 1 obsolete and completely replaces it.
How does it work? Instead of single strategy (and single Kalman filter), the whole grid of Kalman filters is evaluated by a proprietary system at the same time. Then, machine learning principles are applied to rank particular Kalman filter performances. Another algorithm is then used to figure filter outputs (slope, intercept, standard deviation) from the whole grid. The whole system actually behaves like a single Kalman filter, but with no need to provide any parameters.
Main advantages of this model:
- it squeezes all profit from the pair
- beats any other models in performance (in average) and also in performance per day-in-position
- no risk of over-fitting in parameter optimization (nothing to optimize, except thresholds)
Issues of this model:
- you still need to set entry/exit thresholds - basically this affect number of trades and slot usage...exit threshold is usually 0, try entry threshold from range <2,4>
- the simple A.I. inside is profit-based - so not-so-good pairs with waves in profit can "fool" the algorithm so it falls from the optimum
- model performance is proportional to margin usage
- evaluating this model needs a lot of memory and processing resources
Specialties:
- if you set entry threshold to 1, exit threshold to -1, model to "simple" and if you allow reversals, the model will be "always-in-position" squeezing the most profit from good pairs
To give some insight on performance: we took 300 best performing pairs from PTL database in period Jan 2013 - Jan 2016. Then we backtested all 300 pairs using out-of-sample period (Jan 2016 - Sep 2016) and we compared their performance. Models used: Ratio(per 14), Residual(20), Kalman Grid v1, Kalman Grid v2 using exit threshold of 0 (normal) and -1 (aggressive). Margin 50% (Req-T). Results here:
Model | Median CAGR % | Mean CAGR % |
Kalman-grid v2 (normal) | 7.206409 | 9.538509 |
Kalman-grid v2 (aggressive) | 7.088950 | 11.433199 |
Kalman-grid v1 | 4.877391 | 10.794117 |
Residual(20) | 3.596212 | 6.631089 |
Ratio(14) | 3.590883 | 8.954484 |
[edit] Model Support
- in PTL backtester: yes
- in PTL portfolio backtester: yes
- in PTL Trader: since v1.4.0
[edit] Model Parameters
- entry threshold E_{n} for Z-score, typical value range is <1, 4>
- exit threshold E_{x} for Z-score, typical value is <-1, 00>...negative values allowed (allows to exit at other side)
- downtick threshold E_{d} for Z-score, typical value is <0, 1>...used for downtick mode only as a third band (not used often)
- max Z-score E_{max} (optional, to filter out extremes, typical value is >10 if used)
- entry mode (simple, uptick, downtick)
[edit] Model Neutrality
For Kalman Grid Model, we support both dollar neutral (equal dollar amount invested to each leg) and beta neutral regimes.
[edit] Entering & Exiting Positions
Same as in Residual Model.
[edit] Kalman-Auto Model
This model is very similar to Kalman-grid model, it is like his younger brother. The main difference is that the simple A.I. of this model is not trying to work with profit (which is problem with certain kind of pairs). Instead, it justs tries to find optimum δ (transition covariance) of the Kalman filter together with the entry threshold to match the margin usage target. An example: you can set this model to try to optimize everything so the strategy spends 50% time in position (so if you traded one year, the model spent only half a year in positions). Or you can say the average slot usage (margin usage) is 50%. This is useful for trading whole portfolios of Kalman-Auto based strategies, so you can fine tune the diversification inside the portfolio correctly.
Advantages of this model:
- the only parameter to fine-tune of this model is (apart from the usage target) V_{e} (Kalman filter observation covariance), which is luckily not sensitive
- the model is much faster to evaluate than Kalman-Grid
- the simple A.I. of this model is robust and not-so easy to fool
- entry threshold is side-product of the self-optimization!
This is the model you need if you don't want to spent hours of optimizing parameters. You just tell it to trade and stay in position 60% of the time and that's it. On the other hands, it does not match in profits with Kalman-Grid for very good pairs (but actually it has similar performance when you divide the profit to the margin usage).
Please note there is no regulation feedback loop inside, the self optimization works just with ring-buffer with follows the current point and it is used for finding best parameters. So do not expect you set the target to 80% and at the end you get 80% portfolio usage. The good working range is <40, 60>.
Example: Visa/Mastercard backtest with Usage Target set to 60%. Notice the % Days In Trade resulted in 64.9%.
[edit] Model Support
- in PTL backtester: yes
- in PTL portfolio backtester: yes
- in PTL Trader: since v1.4.0
[edit] Model Neutrality
For Kalman-Auto Model, we support both dollar neutral (equal dollar amount invested to each leg) and beta neutral regimes.
[edit] Model Parameters
- Kalman filter observation covariance V_{e}, typical value is 0.001
- desired margin usage threshold in %, allowed range <20, 80>, the range <40,60> works the best in terms of how precise is the margin usage matched to the target
[edit] Entering & Exiting Positions
Same as in Residual Model, but:
- entry threshold is figured automatically by the model
- exit threshold is always 0
- entry mode is always "simple"
[edit] Deprecated Models
- Orthogonal Model
- Kalman-grid Model (v1)