StockFetcher Forums · Filter Exchange · A NEW ^VIX TRADING SYSTEM<< 1 2 3 4 5 ... 49 >>Post Follow-up
Kevin_in_GA
4,599 posts
msg #130879
Ignore Kevin_in_GA
9/5/2016 6:14:55 PM

I have been tinkering with Stratasearch (again) and wanted to share some of my work here at SF. It should be noted that Stratasearch has a greater range of accessible functions and indicators, as well as a more expansive ability to generate user-defined functions. Another really nice thing SS can do is to run a vast number of possible indicator combinations against a stock or set of stocks over any defined time period. This brute force calculational approach usually discovers lots of interesting results that can be profitably traded, but there are many times when the results of a Stratasearch optimzation cannot be directly translated into SF code.

I decided to use this approach to find trading strategies against the ^VIX index over the last 5 years (from 9/1/2011 through 9/1/2016). During this time the ^VIX mostly went DOWN, not UP so one would expect a lot more short strategies than long ones. I allowed SS to run over 2 million different combinations of indicators, requiring only that the results

1. Have a win % of 90% or higher
2. Have completed at least 20 trades over the 5 year period, and
3. Be held no longer than 10 days

My objective was to find 10 successful long and 10 successful short ^VIX trading strategies that meet these requirements, and to combine them into a single trading system which allocates equal portions of your equity to each strategy, trading that portion only when a signal for that strategy is triggered. The entire screening process (over 2 million different combinations) only took about 24 hours since it was against a single set of index data.

I looked for systems that had high Sharpe ratios and high annual returns. I also wanted to be sure that the entry signals were not just very minor variations of a single trigger - each had to employ a unique entry signal to be included in the final multi-system. All trades were entered as market orders at the open of the day after the signal was triggered - same for trade exits. Since these are independent strategies each has its own entry and exit signals, and often you will be holding both long and short positions on the index at the same time (again, each system is independent of the others and does not know or care if you are holding the opposite position as well since both are valid trades).

PART I: FIRST, THE RESULTS ...

The equity curve:


equity curve 2011-2016 photo new vix equity curve 2011-2016_zpsvg0mwy19.gif

The system results are in blue, while the S&P 500 returns for the same time period are displayed in red.

The stats:


 photo new vix results 2011-2016_zpsqtichfym.gif


And the absolute number of open positions at any time during the test period:


 photo position count_zpsxbcx0xeq.gif


This is actually pretty important -
my initial thought was that I would divide my investment funds into 20 "slices" and only trade a slice when the corresponding filter triggered, but looking at the position counts it is very clear that if I did that I would be trading only a fraction of my available capital - it looks like the system rarely had more than 5 positions open at any time, so you make the best returns just trading five units whenever ANY filter triggers.


A REALLY IMPORTANT POINT TO MAKE: THE SYSTEM SIGNALS ARE TRIGGERED BY THE VIX INDEX - YOU HAVE TO MAKE THE TRADES USING A SURROGATE (EITHER OPTIONS, FUTURES, OR ETFs/ETNs).

The results seen here are for the ^VIX index, which cannot be traded.
Instead, you will have to use these signals to trade either options, futures, or one of several ETFs/ETNs that try to track the index. For most of us, the easiest thing to trade are the ETFs and ETNs, but there is a caveat. I have seen that instruments like VXX and XIV show only about one third the gains/losses of the index, so please do not expect 200% returns each year - it will more likely be a third to a quarter of that amount. Also, these ETFs do not mirror the index as well as most people think - in fact there are times when they will show a loss when the index would have gained, and vice versa.


PART II: THE RISK OF OVERFITTING ...

Whenever you cherry pick 20 strategies out of over 2,000,000, you really ought to be very careful about overfitting. Having every day of results and running a backtest against them almost guarantees a good result, but makes no promise about how those strategies might perform against data that is outside of the same period used in the search. The most obvious thing about the ^VIX during the period 2011-2016 is that it went down a lot during a time of almost unprecedented stock market gains. In order to be at all useful, trading systems must be tested against "out-of-sample" data and need to show decent performance against a range of market conditions, ideally containing short-term market dislocations and both recessionary and strong recovery periods.

To that end, I took these "Top 20" filters and applied them against the ^VIX for the period 9/1/1999 through 9/1/2009 (10 years of new data, all out of sample). I did nothing to adjust the strategy parameters, just wanted to see how well or badly they would have performed.

Here are the results:

The equity curve:

new vix equity curve 1999-2009 photo new vix equity curve 1999-2009_zpstqchsrhx.gif

The Stats:

new vix results 1999-2009 photo new vix results 1999-2009_zps2xnh94by.gif

I had honestly expected them to perform like crap, but it looks like they did exceptionally well against the out-of-sample data.



PART III: THE FILTERS

Here are the complete SS codes for each system, and to the extent that I can I have also included the corresponding SF code. Not all of the filters translate into SF code, and in some cases I am making approximations due to the limits of SF code structure and functions.

VIX LONG SIGNAL #1:

ENTRY:
// Accumulation Swing Index: 2 (Primary)
(crossbelow(asi(100), mov(asi(100), 20, simple))) and

// On Balance Volume - Market Periods: 1 (Supporting Entry and Exit)
(high(obv(), 25) = high(obv(), 65)) and

// Price Channels - Market (Supporting Entry)
(pcu(15)-pcl(15) < mov(pcu(15)-pcl(15), 15, simple))


EXIT:
// Accumulation Swing Index: 2 (Primary)
(crossabove(asi(100), mov(asi(100), 20, simple))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10) or

// On Balance Volume - Market Periods: 1 (Supporting Entry and Exit)
(high(obv(), 25) <> high(obv(), 65))


Not readily translatable into SF code - the accumulation swing index here on SF does not specify how many days of accumulation are used, and there is no functional equivalent for Price channels.

VIX LONG SIGNAL #2:

ENTRY:
// Aroon Crossover: 2 (Primary)
(crossbelow(aroonu(11), aroond(11))) and

// Moving Average Crossover - Sector: 2 (Supporting Entry)
(mov(close, 3, simple) < mov(close, 60, simple))


EXIT:
// Aroon Crossover: 2 (Primary)
(crossabove(aroonu(11), aroond(11))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF except for the maximum 10 day hold, which you will need to keep track of.

Fetcher[
symlist(vxx,tvix,uvxy)
/*ENTRY CONDITIONS*/
set{arooncrossbelow, count(ind(^vix, aroon up(11)) crossed below ind(^vix, aroon down(11)), 1)}
set{ma3belowma60, count(ind(^vix, MA(3)) below ind(^vix, ma(60)), 1)}
set{entry, arooncrossbelow * ma3belowma60}

/*EXIT CONDITIONS*/
set{exit, count(ind(^vix, aroon up(11)) crossed above ind(^vix, aroon down(11)), 1)}
set{10dayexit, count(days(entry above 0.5, 10) above 9,1)}

add column entry {long entry}
add column separator
add column exit
]



VIX LONG SIGNAL #3:

ENTRY:
// Envelopes: 2 (Primary)
(crossbelow(close, envl(25, 6, simple))) and

// Stochastics Crossover - Stock: 1 (Supporting Entry)
(stochk(3, 4) > stochd(3, 4, 5, simple))


EXIT:
// Envelopes: 2 (Primary)
(crossabove(close, envu(25, 6, simple))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF except for the maximum 10 day hold, which you will need to keep track of.

Fetcher[
symlist(vxx,tvix,uvxy)
/*ENTRY CONDITIONS*/
set{closebelowenvl, count(ind(^vix, close) crossed below ind(^vix, Lower SMA Envelope(25,6.0)), 1)}
set{stochcross, count(ind(^vix, Stochastic %K(3,4)) above ind(^vix, Stochastic %D(3,4,5)), 1)}
set{entry, closebelowenvl * stochcross}

/*EXIT CONDITIONS*/
set{exit, count(ind(^vix, close) crossed above ind(^vix, Upper SMA Envelope(25,6.0)), 1)}
set{10dayexit, count(days(entry above 0.5, 10) above 9,1)}

add column entry {long entry}
add column separator
add column exit
]



VIX LONG SIGNAL #4:

ENTRY:
// Momentum Divergence: 1 (Primary)
(close = low(close, 15) and mom(close, 9) <> low(mom(close, 9), 15)) and

// Directional Movement - Sector Periods: 2 (Supporting Entry and Exit)
(pdi(14) < mdi(14))


EXIT:
// Momentum Divergence: 1 (Primary)
(close = high(close, 15) and mom(close, 9) <> high(mom(close, 9), 15)) or

// Directional Movement - Sector Periods: 2 (Supporting Entry and Exit)
(pdi(14) > mdi(14))or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF except for the maximum 10 day hold, which you will need to keep track of.

Fetcher[
symlist(vxx,tvix,uvxy)
/*ENTRY CONDITIONS*/
set{entry1a, count(ind(^VIX,close) reached a new 15 day low, 1)}
set{mom9low, ind(^vix, momentum(9) 15 day low)}
set{entry1b, count(ind(^vix, momentum(9)) above mom9low, 1)}
set{entry1, entry1a * entry1b}
set{entry2, count(ind(^vix, pdi(14)) below ind(^vix, mdi(14)), 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{exit1, count(ind(^vix, close) reached a new 15 day high, 1)}
set{mom9high, ind(^vix, momentum(9)) 15 day high}
set{exit2, count(ind(^vix, momentum(9)) below mom9high, 1)}
set{exit3, exit1 * exit2}
set{exit4, count(ind(^vix, pdi(14)) above ind(^vix, mdi(14)), 1)}
set{exit, exit3 + exit4}

add column entry {long entry}
add column separator
add column exit
]



VIX LONG SIGNAL #5:

ENTRY:
// Stochastics Crossover: 2 (Primary)
(crossbelow(stochk(9, 4), stochd(9, 4, 9, simple))) and

// Aroon Crossover - Stock: 2 (Supporting Entry)
(aroonu(15) < aroond(15))


EXIT:
// Stochastics Crossover: 2 (Primary)
(crossabove(stochk(9, 4), stochd(9, 4, 9, simple))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF except for the maximum 10 day hold, which you will need to keep track of.

Fetcher[
symlist(vxx,tvix,uvxy)
/*ENTRY CONDITIONS*/
set{stochcross, count(ind(^vix, Stochastic %K(9,4)) crossed below ind(^vix, Stochastic %D(9,4,9)), 1)}
set{arooncross, count(ind(^vix, aroon up(15)) below ind(^vix, aroon down(15)), 1)}
set{entry, arooncross * stochcross}

/*EXIT CONDITIONS*/
set{exit, count(ind(^vix, Stochastic %K(9,4)) crossed above ind(^vix, Stochastic %D(9,4,9)), 1)}
set{10dayexit, count(days(entry above 0.5, 10) above 9, 1)}

add column entry {long entry}
add column separator
add column exit
]



VIX LONG SIGNAL #6:

ENTRY:
// Bollinger Bands: 1 (Primary)
(close < bbl(close, 13, 0.5)) and

// Momentum Divergence - Sector: 1 (Supporting Entry)
(close = low(close, 60) and mom(close, 9) <> low(mom(close, 9), 60)) and

// Money Flow Index - Sector Periods: 1 (Supporting Entry and Exit)
(mfi(20) < 85)


EXIT:
// Bollinger Bands: 1 (Primary)
(close > bbl(close, 13, 0.5)) or

// Money Flow Index - Sector Periods: 1 (Supporting Entry and Exit)
(mfi(20) > 85) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF except for the maximum 10 day hold, which you will need to keep track of.

Fetcher[
symlist(vxx,tvix,uvxy)
/*ENTRY CONDITIONS*/
set{belowbbl, count(ind(^vix, close) below ind(^vix, lower Bollinger Band(13,0.5)), 1)}
set{moneyflow, count(ind(^vix, mfi(20)) below 85, 1)}
set{entry1a, count(ind(^VIX,close) reached a new 60 day low, 1)}
set{mom60low, ind(^vix, momentum(9) 60 day low)}
set{entry1b, count(ind(^vix, momentum(9)) above mom60low, 1)}
set{entry1, entry1a * entry1b}
set{entry2, belowbbl * moneyflow}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{abovebbl, count(ind(^vix, close) above ind(^vix, lower Bollinger Band(13,0.5)), 1)}
set{moneyflow2, count(ind(^vix, mfi(20)) above 85, 1)}
set{exit, abovebbl + moneyflow2}

add column entry {long entry}
add column separator
add column exit
]



VIX LONG SIGNAL #7:

ENTRY:
// TEMA: 2 (Primary)
(crossbelow(tema(close, 7), tema(close, 40))) and

// Moving Average Crossover - Stock Periods: 2 (Supporting Entry and Exit)
(mov(close, 9, simple) < mov(close, 40, simple))


EXIT:
// TEMA: 2 (Primary)
(crossabove(tema(close, 7), tema(close, 40))) or

// Moving Average Crossover - Stock Periods: 2 (Supporting Entry and Exit)
(mov(close, 9, simple) > mov(close, 40, simple))

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


The triple exponential moving average used here (TEMA) does not have an exact SF counterpart - the closest thing is a triple exponential function called T3 but I cannot verify if it is the same since it requires two parameters versus only one for the SS version. Therefore I would not use it since it would likely give different signals.

VIX LONG SIGNAL #8:

ENTRY:
// Directional Movement: 2 (Primary)
(crossbelow(pdi(16), mdi(16))) and

// Projection Bands - Market (Supporting Entry)
(pbu(15)-pbl(15) < mov(pbu(15)-pbl(15), 15, simple))


EXIT:
// Directional Movement: 2 (Primary)
(crossabove(pdi(16), mdi(16))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF except for the maximum 10 day hold, which you will need to keep track of.

Fetcher[
symlist(vxx,tvix,uvxy)
/*ENTRY CONDITIONS*/
set{entry1, count(ind(^vix, pdi(16)) crossed below ind(^vix, mdi(16)), 1)}
set{pbanddiff, ind(^vix, Upper Projection Band(15)) - ind(^vix, Lower Projection Band(15))}
set{pbandma, cma(pbanddiff, 15)}
set{entry2, count(pbanddiff below pbandma, 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{exit, count(ind(^vix, pdi(16)) crossed above ind(^vix, mdi(16)), 1)}}

add column entry {long entry}
add column separator
add column exit
]



VIX LONG SIGNAL #9:

ENTRY:
// Qstick Crossover: 2 (Primary)
(crossbelow(qst(16), 0)) and

// Accumulation Swing Index - Market Periods: 1 (Supporting Entry and Exit)
(sector($curexchange, asi(100)) > sector($curexchange, mov(asi(100), 30, simple)))


EXIT:
// Qstick Crossover: 2 (Primary)
(crossabove(qst(16), 0)) or

// Accumulation Swing Index - Market Periods: 1 (Supporting Entry and Exit)
(sector($curexchange, asi(100)) < sector($curexchange, mov(asi(100), 30, simple))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


Same issue as in VIX LONG #1, the period for SF's ASI function is unknown, so I would not code this since it is likely to give different signals from those generated by SS.


VIX LONG SIGNAL #10:

ENTRY:
// Commodity Channel Index (Classic): 2 (Primary)
(crossbelow(cci(19), -119)) and

// Price Oscillator - Market Periods: 1 (Supporting Entry and Exit)
(sector($curexchange, po(3, 60, exponential)) > 0)


EXIT:
// Commodity Channel Index (Classic): 2 (Primary)
(crossabove(cci(19), -119)) or

// Price Oscillator - Market Periods: 1 (Supporting Entry and Exit)
(sector($curexchange, po(3, 60, exponential)) < 0) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


Stratasearch can use sector-based and exchange-based functions (SF cannot) so in this filter the Price Oscillator should translate over to just ^VIX since there is no sector or exchange for it, but I have not confirmed this yet. Also, the moving average used in SS is exponential and in SS it is simple. Caveat.

Fetcher[
symlist(vxx,tvix,uvxy)
/*ENTRY CONDITIONS*/
set{entry1, count(ind(^vix, cci(19)) crossed below -119, 1)}
set{entry2, count(ind(^vix, ppo(3,60)) above 0, 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{exit1, count(ind(^vix, cci(19)) crossed above -119, 1)}
set{exit2, count(ind(^vix, ppo(3,60)) below 0, 1)}
set{exit, exit1 + exit2}

add column entry {long entry}
add column separator
add column exit
]



VIX SHORT SIGNAL #1:

ENTRY:
// Price Rate-of-Change Divergence: 2 (Primary)
(close = high(close, 10) and proc(close, 13) <> high(proc(close, 13), 10)) and

// Dynamic Momentum Divergence - Sector Periods: 2 (Supporting Entry and Exit)
(diverge(dmi(), mov(close, 3, simple), 4, 11) <> 1)


EXIT:
// Price Rate-of-Change Divergence: 2 (Primary)
(close = low(close, 10) and proc(close, 13) <> low(proc(close, 13), 10)) or

// Dynamic Momentum Divergence - Sector Periods: 2 (Supporting Entry and Exit)
(diverge(dmi(), mov(close, 3, simple), 4, 11) = 1) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


SF does not have a DMI() indicator so I cannot code this one.


VIX SHORT SIGNAL #2:

ENTRY:
// Projection Oscillator Divergence: 2 (Primary)
(diverge(pjo(5), mov(close, 3, simple), 0, 5) = -1) and

// Stochastic Momentum Index - Stock: 2 (Supporting Entry)
(smi(3, 2, 2) > 32)


EXIT:
// Projection Oscillator Divergence: 2 (Primary)
(diverge(pjo(5), mov(close, 3, simple), 0, 5) = 1) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


Here we encounter the SS diverge() function, which I had requested SF build a while back (they did). However, it cannot be used within set{} statements or when using custom user functions. Luckily it can be coded using a lot more set{} statements.

Fetcher[
symlist(xiv,svxy)
/*ENTRY CONDITIONS*/
set{entry1, count(ind(^vix, smi(3,2,2)) above 32,1)}
SET{PJO_UP, COUNT(ind(^vix, projection oscillator(5)) GAINED MORE THAN 0% OVER THE LAST 5 DAYS,1)}
SET{PJO_DN, COUNT(ind(^vix, projection oscillator(5)) DROPPED MORE THAN 0% OVER THE LAST 5 DAYS,1)}

SET{MA3_UP, COUNT(ind(^vix, MA(3)) GAINED MORE THAN 0% OVER THE LAST 5 DAYS,1)}
SET{MA3_DN, COUNT(ind(^vix, MA(3)) DROPPED MORE THAN 0% OVER THE LAST 5 DAYS,1)}

SET{POS_DIV, PJO_UP * MA3_DN}
SET{NEG_DIV, PJO_DN * MA3_UP}

set{entry2, count(NEG_DIV above 0.5, 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{exit, count(POS_DIV above 0.5, 1)}

add column entry {short entry}
add column separator
add column exit
]



VIX SHORT SIGNAL #3:

ENTRY:
// Price Rate-of-Change Divergence: 2 (Primary)
(close = high(close, 15) and proc(close, 5) <> high(proc(close, 5), 15)) and

// TRIX - Sector Periods: 1 (Supporting Entry and Exit)
(trix(close, 5) > mov(trix(close, 5), 25, simple))


EXIT:
// Price Rate-of-Change Divergence: 2 (Primary)
(close = low(close, 15) and proc(close, 5) <> low(proc(close, 5), 15)) or

//TRIX - Sector Periods: 1 (Supporting Entry and Exit)
(trix(close, 5) < mov(trix(close, 5), 25, simple)) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF as follows, but not the 10 day hold.

Fetcher[
symlist(xiv,svxy)
/*ENTRY CONDITIONS*/
set{entry1a, count(ind(^VIX, close) reached a new 15 day high, 1)}
set{prochigh, ind(^vix, proc(5,1)) 15 day high}
set{entry1b, count(ind(^vix, proc(5,1)) below prochigh, 1)}
set{entry1, entry1a * entry1b}

set{entry2, count(ind(^vix, trix(5)) above cma(ind(^vix, trix(5)),25), 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{exit1a, count(ind(^VIX, close) reached a new 15 day low, 1)}
set{proclow, ind(^vix, proc(5,1)) 15 day low}
set{exit1b, count(ind(^vix, proc(5,1)) above proclow, 1)}
set{exit1, entry1a * entry1b}

set{exit2, count(ind(^vix, trix(5)) below cma(ind(^vix, trix(5)),25), 1)}
set{exit, exit1 + exit2}

add column entry {short entry}
add column separator
add column exit
]



VIX SHORT SIGNAL #4:

ENTRY:
// Moving Average Crossover: 1 (Primary)
(crossabove(mov(close, 1, simple), mov(close, 15, simple))) and

// Envelopes - Stock: 2 (Supporting Entry)
(close > envu(15, 7, simple))


EXIT:
// Moving Average Crossover: 1 (Primary)
(crossbelow(mov(close, 1, simple), mov(close, 15, simple))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF as follows, but not the 10 day hold.

Fetcher[
symlist(xiv,svxy)
/*ENTRY CONDITIONS*/
set{entry1, count(ind(^vix, close) crossed above cma(ind(^vix, close),15), 1)}
set{entry2, count(ind(^vix, close) above ind(^vix, upper sma envelope(15,7)), 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/

set{exit, count(ind(^vix, close) crossed below cma(ind(^vix, close),15), 1)}

add column entry {short entry}
add column separator
add column exit
]



VIX SHORT SIGNAL #5:

ENTRY:
// TRIX: 1 (Primary)
(increasing(trix(close, 9))) and

// Stochastic Momentum Index - Sector Periods: 2 (Supporting Entry and Exit)
(smi(5, 4, 4) > 30)


EXIT:
// TRIX: 1 (Primary)
(decreasing(trix(close, 9))) or

// Stochastic Momentum Index - Sector Periods: 2 (Supporting Entry and Exit)
(smi(5, 4, 4) < -32) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF as follows, but not the 10 day hold.

Fetcher[
symlist(xiv,svxy)
/*ENTRY CONDITIONS*/
set{entry1, count(ind(^vix, trix(9)) above ind(^vix, trix(9)) 1 day ago, 1)}
set{entry2, count(ind(^vix, smi(5,4,4)) above 30, 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/

set{exit1, count(ind(^vix, trix(9)) below ind(^vix, trix(9)) 1 day ago, 1)}
set{exit2, count(ind(^vix, smi(5,4,4)) below -32, 1)}
set{exit, exit1 + exit2}

add column entry {short entry}
add column separator
add column exit
]



VIX SHORT SIGNAL #6:

ENTRY:
// Price Channels: 1 (Primary)
(close > pcu(5) and pcu(5)-pcl(5) < mov(pcu(5)-pcl(5), 5, simple)) and

// Price Rate-Of-Change - Sector: 2 (Supporting Entry)
(proc(close, 14) > 6)


EXIT:
// Price Channels: 1 (Primary)
(close < (pcu(5)+pcl(5))/2) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This cannot be coded in SF due to the lack of a price channel function.

VIX SHORT SIGNAL #7:

ENTRY:
// Price Oscillator: 1 (Primary)
(crossabove(po(3, 25, exponential), 0)) and

// Stochastic Momentum Divergence - Market: 2 (Supporting Entry)
(sector($curexchange, diverge(smi(3, 4, 4), mov(close, 3, simple), 5, 19)) = -1)


EXIT:
// Price Oscillator: 1 (Primary)
(crossbelow(po(3, 25, exponential), 0)) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF but the way in which Stratasearch treats "sectors" and "exchanges" may yield different signals. Caveat.

Fetcher[
symlist(xiv,svxy)
/*ENTRY CONDITIONS*/
set{entry1, count(ind(^vix, Price Oscillator(3,25)) crossed above 0, 1)}

SET{SMI_UP, COUNT(ind(^vix, SMI(3,4,4)) GAINED MORE THAN 5% OVER THE LAST 19 DAYS,1)}
SET{SMI_DN, COUNT(ind(^vix, SMI(3,4,4)) DROPPED MORE THAN 5% OVER THE LAST 19 DAYS,1)}
SET{MA3_UP, COUNT(ind(^vix, MA(3)) GAINED MORE THAN 5% OVER THE LAST 19 DAYS,1)}
SET{MA3_DN, COUNT(ind(^vix, MA(3)) DROPPED MORE THAN 5% OVER THE LAST 19 DAYS,1)}
SET{POS_DIV, SMI_UP * MA3_DN}
SET{NEG_DIV, SMI_DN * MA3_UP}

set{entry2, count(NEG_DIV above 0.5, 1)}
set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{exit, count(ind(^vix, Price Oscillator(3,25)) crossed below 0, 1)}

add column entry {short entry}
add column separator
add column exit
]



VIX SHORT SIGNAL #8:

ENTRY:
// Price Channels: 1 (Primary)
(close > pcu(5) and pcu(5)-pcl(5) < mov(pcu(5)-pcl(5), 5, simple)) and

// R-Squared - Sector (Supporting Entry)
( rsq(close, 20) > .20)


EXIT:
// Price Channels: 1 (Primary)
(close < (pcu(5)+pcl(5))/2) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This cannot be coded in SF since there is no equivalent price channel function

VIX SHORT SIGNAL #9:

ENTRY:
// Linear Regression Indicator: 1 (Primary)
(crossabove(close, lri(close, 20) * 0.97)) and

// Bollinger Bands - Market: 1 (Supporting Entry)
(sector($curexchange, close) < sector($curexchange, bbl(close, 10, 0.5)))


EXIT:
// Linear Regression Indicator: 1 (Primary)
(crossbelow(close, lri(close, 20) * 0.97)) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This can be coded in SF but the way in which Stratasearch treats "sectors" and "exchanges" may yield different signals. Caveat.

Fetcher[
symlist(xiv,svxy)
/*ENTRY CONDITIONS*/
set{lrientry, ind(^vix, lri(20)) * 0.97}
set{entry1, count(ind(^vix, close) crossed above lrientry, 1)}
set{entry2, count(ind(^vix, close) below ind(^vix, lower Bollinger Band(10,0.5)), 1)}

set{entry, entry1 * entry2}

/*EXIT CONDITIONS*/
set{exit, count(ind(^vix, close) crossed below lrientry, 1)}

add column entry {short entry}
add column separator
add column exit
]



VIX SHORT SIGNAL #10:

ENTRY:
// TEMA: 1 (Primary)
(crossabove(tema(close, 3), tema(close, 55))) and

// TRIX Divergence - Sector Periods: 2 (Supporting Entry and Exit)
(sector("VIX", close) <> sector("VIX", low(close, 20)) or
sector("VIX", trix(close, 15)) = sector("VIX", low(trix(close, 15), 20))) and

// Vertical Horizontal Filter - Sector (Supporting Entry)
(sector("VIX", vhf(9)) > 0.4)


EXIT:
// TEMA: 1 (Primary)
(crossbelow(tema(close, 3), tema(close, 55))) or

// TRIX Divergence - Sector Periods: 2 (Supporting Entry and Exit)
(sector("VIX", close) = sector("VIX", low(close, 20)) and
sector("VIX", trix(close, 15)) <> sector("VIX", low(trix(close, 15), 20))) or

// Maximum Days Held (Supporting Exit)
($daysheld > 10)


This cannot be directly coded in SF because of a lack of the TEMA() function.


PART IV: SHARING CURRENT (AND FUTURE) SIGNALS


As of 9/2/2016 there is one new Long signal trigger (from VIX LONG SIGNAL #1) and one Short position being held since the open on 8/29 from VIX SHORT SIGNAL #1 (shorting the ^VIX at 14.09, it is currently at 11.98). The new long position should be entered at the open on Tuesday. There are no other open positions or signals right now.

I will post any new signal or changes in positions taken as the signals occur. At your own discretion you may enter positions using VXX/TVIX/UVXY (for Longs) or XIV/SVXY (for shorts) but remember that the signals are based ON THE INDEX and not on the ETFs, and typically the ETFs do not perfectly mirror the index in magnitude or even direction at times.

I'm sharing these with the SF community to provide folks here with a new set of strategies to add to their trading armory. Hopefully this will help both new and more experienced traders to be successful in what is clearly a challenging effort - making money.

shillllihs
6,044 posts
msg #130880
Ignore shillllihs
modified
9/5/2016 7:26:14 PM

So I'm trying to understand this since I'm in a Labor Day bbq food coma, 1 should have 2 positions open, 1 in Tvix and 1 in Xiv. How much of each, equal parts?
Or should the short position be closed out Tuesday or is that position closed?

Kevin_in_GA
4,599 posts
msg #130882
Ignore Kevin_in_GA
modified
9/5/2016 7:42:26 PM

The system trades a "unit" which is always the same size or dollar value.

Also, you are using a 2x leveraged ETF for long but only an inverse for short. You might be better using VXX and XIV since the backtesting assumes equal leverage long and short.

Short position stays open, already at a profit. A new long position is opened tomorrow at the open. Likely that the short position will be closed soon (at a profit), while the long position stays open.

That is how multiple long and short positions can be held simultaneously - they open and close at different times, but mostly both close for a profit (win rates are close to 90+% for all 20 systems listed).

shillllihs
6,044 posts
msg #130885
Ignore shillllihs
modified
9/5/2016 7:59:24 PM

I considerd using units to trade the same instrument long and short years ago,
I knew it was a good idea but had trouble justifying being long and short
at the same time. Since some indicators would point long, while others a few days
later would point short simultaneously, it made sense. So how would you handle
the higher leverage of Tvix to Xiv?

compound_gains
222 posts
msg #130886
Ignore compound_gains
9/5/2016 8:15:19 PM

Nice work Kevin, as always. If someone was going to trade this I'd be inclined to look at VIX options, perhaps three months out, deep-in-the-money, calls or puts depending on whether you're going long or short. IMO, and I think it's largely substantiated, the VIX-related ETNs (VXX, VXZ, TVIX, XXV, XIV) tend to be a curse on investors, especially if you're looking to go long, and don't particularly reflect VIX movement for several different reasons.

Kevin_in_GA
4,599 posts
msg #130887
Ignore Kevin_in_GA
9/5/2016 8:18:08 PM

So how would you handle the higher leverage of Tvix to Xiv?


The specific instrument you choose is up to you - higher returns for TVIX but also a potentially larger drawdown. The simple solutions are:
1. Take a half position in TVIX versus a full position in VXX (lower risk, lower potential return).
1. Ignore the difference since each long trade is independent of any simultaneous short trade (higher risk, higher total return).
3. Take a double position in XIV if you plan to trade TVIX (highest risk, highest return).

My point was only that in the backtest the leverage was the same - trading TVIX instead of VXX should work as well and provide a higher return.

StefanM
25 posts
msg #130891
Ignore StefanM
9/6/2016 3:27:59 AM

@Kevin, did you create a Mulri-System in StrataSearch and then run a Walk-Forward Analysis? I also use StrataSearch, but it is not so easy for me to understand, German is my first language and my trading style has been more discretionary, so all this is quite new to me ..

Kevin_in_GA
4,599 posts
msg #130892
Ignore Kevin_in_GA
9/6/2016 7:38:33 AM

No - it is very challenging to run a WFA on a multi-system since it typically uses 4-12 different settings per system which each need to be periodically re-evaluated (e.g., once per month) - raised to the 20th power since it must be done on all 20 systems in the multi-system each time. The goal of a WFA is to see how a system does against new (out-of-sample) data, which I did using the period 1999-2009.

StefanM
25 posts
msg #130893
Ignore StefanM
9/6/2016 8:57:25 AM

Sorry but I only understand partially what you mean. What I want to understand is how you get the 2 equity curves for 20 different setups. Obviously you combine them.
You run a brute force, find the 20 systems, and combine them in a multi strategy setup? This brings up your first equity curve.
And how do you bring up the second curve with the out-of-sample data? I did not understand if the curve is the result of a WF analyse, of it you used another tool of StrataSearch. I do not ask so much about details of your strategy but more about a "how-to" in StrataSearch ..


Kevin_in_GA
4,599 posts
msg #130895
Ignore Kevin_in_GA
modified
9/6/2016 9:50:04 AM

You combine the 20 systems developed against the data from 2011-2016 into a multi-system. Then you change the trade settings to run over a new period (I chose 1999-2009) and you run the multi-system against that period. That is how the second curve and stats are developed.

I do not ask so much about details of your strategy but more about a "how-to" in StrataSearch

That is what I would like to avoid here - I would rather have this thread be focused on the trading system itself rather than how to do things in Stratasearch. I would suggest reviewing the documentation and looking through the forums over at Stratasearch.com - you will find the answers to most of your questions. Thanks, Kevin

StockFetcher Forums · Filter Exchange · A NEW ^VIX TRADING SYSTEM<< 1 2 3 4 5 ... 49 >>Post Follow-up

*** Disclaimer *** StockFetcher.com does not endorse or suggest any of the securities which are returned in any of the searches or filters. They are provided purely for informational and research purposes. StockFetcher.com does not recommend particular securities. StockFetcher.com, Vestyl Software, L.L.C. and involved content providers shall not be liable for any errors or delays in the content, or for any actions taken based on the content.


Copyright 2022 - Vestyl Software L.L.C.Terms of Service | License | Questions or comments? Contact Us
EOD Data sources: DDFPlus & CSI Data Quotes delayed during active market hours. Delay times are at least 15 mins for NASDAQ, 20 mins for NYSE and Amex. Delayed intraday data provided by DDFPlus


This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.