This is pretty much what we had in our 1st version of the TT_CYCLE & TT_ENTRYPOINT code, so I heartily agree !
Obviously the difference is in how we decided the trigger point. The TT_MTL_CYCLE3 does the same thing but removes the need for Global Variables whilst simultaneously discovering a bug in Tradestation which ensures it occasionally throws out ****ty data.
I thought the same. The TT_MTL_CYCLE3 code makes a good testing framework for oscillators. It's all in one place and allows control of the other factors in trade entry. Generally the oscillator testing code should be similar to, or reuse, the trade entry code. The testing environment is closer to the trading environment and the results easier to compare.
Glenn, I'll put the MACCI SMA cross code in TT_MTL_CYCLE3 for starters and try reproduce something along the lines of your example.
Inputs : Length(5);
Vars : CycleHistory60(0, data6),CycleHistory30(0, data5),CycleHistory10(0, data4),
CycleHistory5(0, data3),CycleHistory3(0, data2),CycleHistory1(0,data1);
// Calculate the indicator for the timeframes
CycleHistory60 = CCI(Length) data6;
CycleHistory30 = cci(Length) data5;
CycleHistory10 = cci(Length) data4;
CycleHistory5 = cci(Length) data3;
CycleHistory3 = cci(Length) data2;
CycleHistory1 = cci(Length) data1;
// Plot cycle 1 as this indicator is for the 1 minute
Plot1(CycleHistory1, "Cycle");
Print(FormatTime( "hh:mm", ElTimeToDateTime( Time ))," Cycles[0] ", CycleHistory60, " ", CycleHistory30, " ", CycleHistory10, " ", CycleHistory5, " ", CycleHistory3, " ", CycleHistory1);
Print(" Cycles[1] ", CycleHistory60[1], " ", CycleHistory30[1], " ", CycleHistory10[1], " ", CycleHistory5[1], " ", CycleHistory3[1], " ", CycleHistory1[1]);
This is an illustration of Glenn's oscillator testing example as it might be done within the TT_MTL_CYCLE3 context. There's currently an issue with invalid data so this is untested.
// Get the cycle value for all timeframes
CycleHistory60 = TTCycle(CycleLength, Smoothing) data6;
CycleHistory30 = TTCycle(CycleLength, Smoothing) data5;
CycleHistory10 = TTCycle(CycleLength, Smoothing) data4;
CycleHistory5 = TTCycle(CycleLength, Smoothing) data3;
CycleHistory3 = TTCycle(CycleLength, Smoothing) data2;
CycleHistory1 = TTCycle(CycleLength, Smoothing) data1;
// Get (Oscillator + 3 SMA) crossover signals for all timeframes
Crossed60 = TT_Osc_Cross_Bar(CycleHistory60, 3, 10);
Crossed30 = TT_Osc_Cross_Bar(CycleHistory30, 3, 10);
Crossed10 = TT_Osc_Cross_Bar(CycleHistory10, 3, 10);
Crossed5 = TT_Osc_Cross_Bar(CycleHistory5, 3, 10);
Crossed3 = TT_Osc_Cross_Bar(CycleHistory3, 3, 10);
Crossed1 = TT_Osc_Cross_Bar(CycleHistory1, 3, 10);
// Long signals for all timeframes
var: Sig60Long(false), Sig30Long(false),Sig10Long(false),Sig5Long(false),Sig3Long(false),Sig1Long(false);
Sig60Long = CycleHistory60 > 80 and Crossed60 < 0;
Sig30Long = CycleHistory30 > 80 and Crossed30 < 0;
Sig10Long = CycleHistory10 > 80 and Crossed10 < 0;
Sig5Long = CycleHistory5 > 80 and Crossed5 < 0;
Sig3Long = CycleHistory3 > 80 and Crossed3 < 0;
Sig1Long = CycleHistory1 > 80 and Crossed1 < 0;
// Short signals for all timeframes
var: Sig60Short(false), Sig30Short(false),Sig10Short(false),Sig5Short(false),Sig3Short(false),Sig1Short(false);
Sig60Short = CycleHistory60 < -80 and Crossed60 > 0;
Sig30Short = CycleHistory30 < -80 and Crossed30 > 0;
Sig10Short = CycleHistory10 < -80 and Crossed10 > 0;
Sig5Short = CycleHistory5 < -80 and Crossed5 > 0;
Sig3Short = CycleHistory3 < -80 and Crossed3 > 0;
Sig1Short = CycleHistory1 < -80 and Crossed1 > 0;
// Get market direction
var: MarketLong(false), MarketShort(false);
MarketLong = (Sig10Long and Sig60Long) or (Sig10Long and Sig30Long);
MarketShort = (Sig10Short and Sig60Short) or (Sig10Short and Sig30Short);
// Get entry direction
var: EntryLong(false), EntryShort(false);
EntryLong = (Sig1Long and Sig3Long) or (Sig1Long and Sig5Long);
EntryShort = (Sig1Short and Sig3Short) or (Sig1Short and Sig5Short);
if MarketLong and EntryLong then
Alert("Buy"); // etc
if MarketShort and EntryShort then
Alert("SellShort"); // etc
Be careful using Crossover commands. I tried them in TS2000 and found it better to use > and <.
e.g. if signal line > macci then long signal
Glenn
lwebb
There are variations with different types of crossover.
If you have an indicator like M653, then the 3sma signal line will respond more quickly to price, so the signal is given when the 3sma moves above or below the 5 sma.
However many (all?) of the Ehler indicators work differently i.e the signal is given when the main line crosses the signal line, not when the signal line crosses the main line.
So if you use Cross over and under you will get incorrect results if you make the wrong comparison between the two lines.
Glenn
I've posted the modified function TT_Osc_Cross below. It's been changed to use the comparision operators (<,>) instead of TradeStation's cross over/under as per your post. The cross is defined as the oscillator line crossing the SMA line.
I'm not entirely sure I follow the distinction of "the signal is given when the main line crosses the signal line, not when the signal line crosses the main line".
An aspect of finding better oscillators involves using Moving Averages which are smoother and react faster than SMA. The reference standard here is the propriatory Jurik MA. Two open-source contenders are the Hull and the Gaussian MAs.
TradeStation forum link to Hull:
https://www.tradestation.com/Discussions/Topic.aspx?Topic_ID=40589
TradeStation forum link to Gauss:
https://www.tradestation.com/Discussions/Topic.aspx?Topic_ID=31076
The chart below shows the CCI smoothed by SMA, Hull and Gauss moving averages respectively. Both the Hull and Gauss cases react faster than the vanilla MACCI; though at the cost of being more whippy (which also makes them better candidates as scalping indicators).