This is read-only version of AFL library entry. Ability to add user formulas
and comment is only available from members-only area.
Details:
Formula name:
Ed Seykota's TSP: Support and Resistance
Author/Uploader:
Mark H. - mdhuang1gmailcom
Date/Time added:
2006-10-08 01:48:31
Origin:
Keywords:
Level:
semi-advanced
Flags:
system,exploration,indicator
DISCLAIMER: Most formulas present in AFL on-line library are submitted
by the users and are provided here on an "as is" and "as available" basis.
AmiBroker.com
makes no representations or warranties of any kind to the contents or the operation
of material presented here. We do not maintain nor provide technical support
for 3rd party formulas. Description:
This is an implementation of Seykota's TSP S-R system.
See http://www.seykota.com/tribe/TSP/SR/index.htm for details.
I have tested it and got identical results (well there is 2-cent difference due to rounding).
Formula:
/*==============================================================================
Global Settings
==============================================================================*/
SetOption("InitialEquity", 1000000);
SetOption("NoDefaultColumns", True );
SetOption("CommissionMode", 2); //$$ per trade
SetOption("CommissionAmount", 0);
SetOption("MarginRequirement", 10);
SetOption("UsePrevBarEquityForPosSizing", True);
SetOption("UseCustomBacktestProc", True );
SetTradeDelays( 0, 0, 0, 0 );
/*==============================================================================
User-defined Functions
==============================================================================*/
function Support(p)
{
sup = LLV(low, p);
sup[0] = low[0];
for (i = 1; i < p; i++)
{
if(low[i] < sup[i-1]) sup[i] = low[i];
else sup[i] = sup[i-1];
}
return sup;
}
function Resistance(p)
{
res = HHV(high, p);
res[0] = high[0];
for (i = 1; i < p; i++)
{
if(high[i] > res[i-1]) res[i] = high[i];
else res[i] = res[i-1];
}
return res;
}
function OptimizeNot(a1, a2, a3, a4, a5)
{
return a2;
}
/*==============================================================================
Entry and Exit Rules
==============================================================================*/
fast = Optimize("Fast", 20, 5, 105, 5);
slow = Optimize("Slow", 140, 20, 420, 20);
FastRes = Resistance(fast);
FastSup = Support(fast);
SlowRes = Resistance(slow);
SlowSup = Support(slow);
heat = 0.05;
// determine longer term trend
// Note: could have problem if current bar is outside of all previous bars
trend[0] = 0;
for(bar= 1; bar < BarCount; bar++)
{
if(high[bar] > SlowRes[bar-1]) trend[bar] = 1;
else if(low[bar] < SlowSup[bar-1]) trend[bar] = -1;
else trend[bar] = trend[bar-1];
}
LastPosition = 0; // 1 - long; -1 - short
PositionRiskStop = 0;
Buy = Sell = Short = Cover = 0;
for(bar = 5; bar < BarCount-1; bar++)
{
// Exit position by protection stop
if(LastPosition == 1)
{
// Sell at stop
if(PositionRiskStop > low[bar] ) // skip if the signal price only touch (=)
the low
{
// We just calculate the exact price to simulate Ed's skid
stopPrice = PositionRiskStop;
ff = min(open[bar], stopPrice) - low[bar];
stopPrice = min(open[bar], stopPrice) - 0.5*ff;
Sell[bar] = 1;
SellPrice[bar] = stopPrice;
TradePrice[bar] = stopPrice;
LastPosition = 0;
}
}
else if(LastPosition == -1)
{
// Cover at stop
if(PositionRiskStop < high[bar]) // skip if the signal price only touch (=)
the high
{
stopPrice = PositionRiskStop;
ff = high[bar] - max(open[bar], stopPrice);
stopPrice = max(open[bar], stopPrice) + 0.5*ff;
Cover[bar] = 1;
CoverPrice[bar] = stopPrice;
TradePrice[bar] = stopPrice;
LastPosition = 0;
}
}
// move the protection stop
if(LastPosition == 1)
{
PositionRiskStop = FastSup[bar];
}
else if(LastPosition == -1)
{
PositionRiskStop = FastRes[bar];
}
else { // Enter position only when last position has been closed
if(trend[bar] == 1)
{
// buy at stop
if( fastRes[bar] < high[bar+1])
{
ff = high[bar+1] - max(open[bar+1], fastRes[bar]);
stopPrice = max(open[bar+1], FastRes[bar]) + 0.5*ff;
f = heat/(FastRes[bar] - FastSup[bar]);
Buy[bar+1] = 1;
BuyPrice[bar+1] = stopPrice;
PositionSize[bar+1] = f; //this value is passed to CBT for position sizing
LastPosition = 1;
PositionRiskStop = FastSup[bar+1];
TradePrice[bar+1] = stopPrice;
bar ++; // skip one bar since next bar has been handled
}
}
else if(trend[bar] == -1)
{
// short at stop
if( fastSup[bar] > low[bar+1])
{
ff = min(open[bar+1], FastSup[bar]) - low[bar+1];
stopPrice = min(open[bar+1], FastSup[bar]) - 0.5*ff;
f = heat/(FastRes[bar] - FastSup[bar]);
Short[bar+1] = 1;
ShortPrice[bar+1] = stopPrice;
PositionSize[bar+1] = f; //this value is passed to CBT for position sizing
LastPosition = -1;
PositionRiskStop = FastRes[bar+1];
TradePrice[bar+1] = stopPrice;
bar ++; // skip one bar since next bar has been handled
}
}
}
}
// close final day for accounting purpose
bar = Barcount-1;
if(LastPosition == 1) { Sell[bar] = 1; SellPrice[bar] =
(low[bar]+close[bar])/2; }
else if(LastPosition == -1) { Cover[bar] = 1; CoverPrice[bar] =
(high[bar]+close[bar])/2; }
/*==============================================================================
Automatic Analysis Action Options
==============================================================================*/
AAAction = Status("action");
if(AAAction == actionIndicator)
{
Plot(FastRes, "FastRes", colorRed);
Plot(SlowRes, "SlowRes", colorPink);
Plot(FastSup, "FastSup", colorGreen);
Plot(SlowSup, "SlowSup", colorBlue);
}
else if(AAAction == actionExplore)
{
Filter = 1;
AddColumn( DateTime(), "Date", formatDateTime );
AddColumn(O, "Open");
AddColumn(H, "High");
AddColumn(L, "Low");
AddColumn(C, "Close");
AddColumn(FastRes, "FastRes");
AddColumn(SlowRes, "SlowRes");
AddColumn(FastSup, "FastSup");
AddColumn(SlowSup, "SlowSup");
AddColumn(Trend, "Trend");
AddColumn(IIf(Buy, Asc("B"), IIf(Sell, Asc("S"), IIf(Short, Asc("H"),
IIf(Cover, Asc("C"), 0)))) , "Signal", formatChar);
AddColumn(TradePrice, "TradePrice");
}
else if(AAAction == actionPortfolio)
{
bo = GetBacktesterObject();
bo.PreProcess(); // Initialize backtester
for( bar=0; bar < BarCount; bar++)
{
eq = bo.Equity;
for ( sig=bo.GetFirstSignal(bar); sig; sig=bo.GetNextSignal(bar) )
{
if (sig.isExit())
{
if(bo.ExitTrade(bar,sig.symbol,sig.Price))
{
_TRACE("EXIT: " + sig.symbol + "@" + sig.Price);
}
}
}
// update stats after closing trades
bo.UpdateStats(bar, 1 );
for ( sig=bo.GetFirstSignal(bar); sig; sig=bo.GetNextSignal(bar))
{
if (sig.isEntry())
{
// sig.PosSize is passed from Phase I.
shares = round((eq*sig.PosSize)/100)*100;
ps = shares * sig.Price;
if(bo.EnterTrade(bar, sig.symbol, sig.IsLong, sig.Price, ps,
sig.PosScore,sig.RoundLotSize))
{
_TRACE("ENTRY: " + sig.symbol + " @" + sig.Price + " PosScore=" +
sig.PosScore + " PosSize=" + ps);
}
}
}
bo.UpdateStats(bar,1); // MAE/MFE is updated when timeinbar is set to 1.
bo.UpdateStats(bar,2);
}
bo.PostProcess(); // Finalize backtester
}
/*==============================================================================
End of Formula
==============================================================================*/
Hi,
This looks very interesting, but I seem to be getting several errors whenever I try to use it including "possible missing ;" and others. I just cut and paste it from the web page. Did I do something wrong?
Cheers
avi
2006-10-08 09:39:19
very nice work!
Mark H. mdhuang1gmailcom 2006-10-08 10:36:31
This is an updated vesion. I have removed all references to "bar+1", which had made it look like it was referencing to the future (although it was not). The the code is also a bit cleaner.
The backtest results are the same as previous version.
/*==============================================================================
Global Settings
==============================================================================*/
SetFormulaName("TT Support Resistance 1.2");
SetOption("InitialEquity", 1000000);
SetOption("NoDefaultColumns", True );
SetOption("CommissionMode", 2); //$$ per trade
SetOption("CommissionAmount", 0);
SetOption("MarginRequirement", 10);
SetOption("UsePrevBarEquityForPosSizing", True);
SetOption("UseCustomBacktestProc", True );
SetTradeDelays( 0, 0, 0, 0 );
/*==============================================================================
User-defined Functions
==============================================================================*/
function Support(p)
{
sup = LLV(low, p);
sup[0] = low[0];
for (i = 1; i < p; i++)
{
if(low[i] < sup[i-1]) sup[i] = low[i];
else sup[i] = sup[i-1];
}
return sup;
}
function Resistance(p)
{
res = HHV(high, p);
res[0] = high[0];
for (i = 1; i < p; i++)
{
if(high[i] > res[i-1]) res[i] = high[i];
else res[i] = res[i-1];
}
return res;
}
function OptimizeNot(a1, a2, a3, a4, a5)
{
return a2;
}
// determine longer term trend
// Note: could have problem if current bar is outside of all previous bars
// the trend can also be calculated within main loop, but put here for clarity
trend[0] = 0;
for(bar= 1; bar < BarCount; bar++) // bar must start from 1, otherwise trend calculation is wrong
{
if(high[bar] > SlowRes[bar-1]) trend[bar] = 1;
else if(low[bar] < SlowSup[bar-1]) trend[bar] = -1;
else trend[bar] = trend[bar-1];
}
// update stats after closing trades
bo.UpdateStats(bar, 1 );
for ( sig=bo.GetFirstSignal(bar); sig; sig=bo.GetNextSignal(bar))
{
if (sig.isEntry())
{
// sig.PosSize is passed from Phase I.
shares = round((eq*sig.PosSize)/100)*100;
ps = shares * sig.Price;
bo.UpdateStats(bar,1); // MAE/MFE is updated when timeinbar is set to 1.
bo.UpdateStats(bar,2);
}
bo.PostProcess(); // Finalize backtester
}
/*==============================================================================
End of Formula
==============================================================================*/
Mark H. mdhuang1gmailcom 2006-10-08 11:32:36
Add the following line in Support() and Resistance() function to avoid display error if you current symbol doesn't have enough bars:
p = min(p,BarCount); // avoid display error
(before for (i = 1; i < p; i++))
Mark H. mdhuang1gmailcom 2006-10-08 11:36:18
Edwin: Make sure the lines are not wrapped when you paste the code to AmiBroker.
Jack
2006-10-09 04:52:11
There is a syntax error in this line:"AddColumn(IIf(Buy, Asc("B"), IIf(Sell, Asc("S"), IIf(Short, Asc("H"), IIf(Cover, Asc("C"), 0)))) , "Signal", formatChar);"
Wouldn't you like to plot the price bars on top of the support and resistance lines?
Mark H. mdhuang1gmailcom 2006-10-09 09:20:22
Jack: make sure you use the latest version of Amibroker and no line wrap. You can apply the formula as an indicator to an existing price chart, so you don't need to plot the price here.
Jack
2006-10-10 04:27:12
Thanks Mark. My AB version was the problem. I can see that sometimes the long and short time support or resistance lines overlap themselfs. Is it a problem or just coincidence?
Mark H.
2006-10-10 11:43:25
Jack: fast and slow values overlapping is normal when the trends are establishing.
Jack
2006-10-11 03:24:45
Thanks for your help and great effort Mark. I am admire people like you who share their ideas with others.
martin artofjoy11 [at] yahoo.com.sg 2006-10-15 11:46:32
hi, this is really great. Save time lot of time to plot SAR.
But when i toggle it fr daily to wkly chart, there r several error as follow, kindly advise
Price:
For (i=1;i<p;i++)
{
if(High[i]>res[i-1]res[i] res[i[=High[i];
else res[i]
Error 10
Subscript out of range.
You must not access arry elements outside 0..(BarCount-1) range.
rob chapman49682 [at] yahoo.com 2007-03-20 09:06:42
I get the same error as Martin and in the same place. Can anyone help? thanks.
Gary gary [at] garynielson.com 2007-03-23 13:06:48
I just downloaded your AFL file -- the updated version where you have removed all references to "bar+1" -- and I am getting an Error 10 when I run a backtest. "Subscript out of range. You must not access array elements outside 0 ... (BarCount-1) range. I am getting it twice on a symbol and then an Error 29: "Variable 'tradeprice' used without having been initialized. I am running 4.90. Any help appreciated.
Mark H.
2007-03-24 20:51:43
Add this line to the Support() and Resistance() functions just before the loop to avoid the error.
p = min(p,BarCount); //avoid out of range error
for(i=1;i<p;i++)...
Mark H.
2007-03-25 01:58:45
To fix: Error 29: "Variable 'tradeprice' used without having been initialized.
uptrend = Flip(H > Ref(SlowRes,-1),Ref(SlowSup,-1) > L);
trend = IIf(uptrend,1,-1);
for(bar = 1; bar < 10 ;bar++){trend[bar] = 0;}//skipping a few bars at the beginning
Buy = Ref(trend,-1) == 1 AND H > Ref(FastRes,-1);
Sell = Cross(Ref(FastSup,-1),L);
Short = Ref(trend,-1) == -1 AND Ref(FastSup,-1) > L;
Cover = Cross(H,Ref(FastRes,-1));
\\\"\\\\\\\\\\\\\\\" characters appear above do not exist in the real code. They are most probably gifts from comment addition procedure of this page. Please remove them while executing the code.