How to plot a tailing stops on a chart from a given start date

OK, guys I have been round and round on this but can't find a reasonable solution. What I want is the ability to plot on a chart a trailing stop from a given start date until the date it is hit. Ideally I would like to be able to choose between a parabolic stop (Welles Wilder) or a Chandelier stop (Chuck Lebeau). To be clear I am not interested in a stop and reverse approach, just a single simple stop, long or short, drawn from a specified entry date to the date it is hit on a closing basis.

This seems like such a simple and absolutely essential idea that I cannot imagine why it is not part of the basic functionality or as least easily achievable on every TA platform, but oddly it is not. Any help greatly appreciated including trail heads, code snippets, or even, bless you, outright solutions.

Beer offered as bounty.

Thanks in advance,

  John Bollinger
1 Like

Will the "entry date" always be the selected bar on the chart, or do you have something else in mind for defining the start of the trade? I assume that direction (long or short) and stop type (PSAR or Chandelier) would be selected as Parameters.

For most types of stops, the most straightforward approach will likely be to loop from the trade entry bar to the exit bar, calculating the stop price for each bar and saving it into an array, and exiting the loop when the stop is violated. When finished, just plot the stop price array.

@BBands there is an example (using ATR trailing stop) of what I believe you are asking for in the "Traders Tips" section from an article in Technical Analysis of Stocks & Commodities.

http://www.amibroker.com/members/traders/06-2009.html
image

3 Likes

Hi Matt,

I hadn't thought of using the selected bar. In my mind you would simply enter a date as a parameter. maybe starting with something like this?

entryDate = ParamDate("Entry Date", "2022-01-01");
stopType = ParamList("Name", "parabolic|chandelier");
chandMult = Param("Chand Mult", 3, 1, 5, 1);
chandLength = Param("Chand Length", 10, 5, 50, 1);
paraStart = Param("Para Start", 0.02, 0.01, 0.1, 0.01);
paraAccel = Param("Para Accel", 0.02, 0.01, 0.1, 0.01);
paraMax = Param("para Max", 0.2, 0.1, 0.5, 0.01);

(paramDate() requires a default date, so I gave it a dummy.)

Best,

 John

Hi,
it's straightforward using arrays in AFL:

// remove part after first exit/cross between trailing stop and close
if (ParamToggle("Display Only First", "No|Yes")) {
	N = BarsSince(Start);
	NB = BarsSince(Buy); NS = BarsSince(Sell);
	NSS = BarsSince(Short); NC = BarsSince(Cover);
	LongTrade = (NB <= N) AND (NS < NB);
	ShortTrade = (NSS <= N) AND (NC < NSS);
	After = trailArray AND (LongTrade OR ShortTrade) ;
	trailArray = IIf(Ref(Flip(After, 0), -1), Null, trailArray); 
}

with

Start = Cross( DateNum(), StartDate-1 ); 

StartDate may be the entry date or some bars before.

Note that there are many issues with the script shared by @portfoliobuilder, here is a fixed version but I could miss something of course, it's a quick hack...


StartDate = ParamDate("Start date", "2022-07-12" );
Start = Cross( DateNum(), StartDate-1 ); 
Started = Flip( Start, 0 );

StopMode = ParamList("Stop Mode", "Fixed|Chandelier|Modified ATR", 1 );
IntradaySignals = ParamToggle("Intraday Signals ?", "No|Yes");
StopLevel = Param("Fixed perc %", 14, 0.1, 50, 0.1)/100;
StopATRFactor = Param("ATR multiple", 4, 0.5, 10, 0.1 );
StopATRPeriod = Param("ATR period", 14, 3, 50 );

// calculate support and resistance levels
if( StopMode == "Fixed" ) // fixed percent trailing stop
{
	sup = C * ( 1 - stoplevel );
	res = C * ( 1 + stoplevel );
}
else // Chandelier ATR-based stop
if( StopMode == "Chandelier" )
{
	sup = C - StopATRFactor * ATR( StopATRPeriod );
	res = C + StopATRFactor * ATR( StopATRPeriod );
}
else
{
	HL = H - L;
	MAHL =  1.5 * MA( HL, StopATRPeriod );
	HiLo = IIf( HL < MAHL, HL, MAHL );
	H1 = Ref( H, -1 );
	L1 = Ref( L, -1 );
	C1 = Ref( C, -1 );
	Href = IIf( L <= H1, H - C1, ( H - C1 ) - ( L - H1 ) / 2 );
	Lref = IIf( H >= L1, C1 - L, ( C1 - L ) - ( L1 - H ) / 2 );

	diff1 = Max( HiLo, HRef );
	diff2 = Max( diff1, LRef );

	ATRmod = Wilders( diff2, StopATRPeriod );

	sup = C - StopATRFactor * ATRmod ;
	res = C + StopATRFactor * ATRmod ;
}

// only use previous bar to compute stop
sup = Ref(sup,-1);
res = Ref(res, -1);

// calculate trailing stop line
if (IntradaySignals) {
	UL = H; LL = L;
} else {
	UL = C; LL = C;
}

trailARRAY = Null;
trailstop = 0;

for(i = 0; i < BarCount; ++i) {
	if (LL[i] > sup[i]) {
		trailStop = sup[i]; UpTrend = 1; break;
	} else if (UL[i] < res[i]){
		trailStop = res[i]; UpTrend = 0; break;
	}
}

Buy = Sell = Short = Cover = 0;
for( ++i; i < BarCount; i++ ) {
	if (UpTrend) {
		if( LL[ i ] > trailstop ) trailstop = Max( trailstop, sup[ i ] ); // UpTrend = 1;
		else {
			trailstop = res[i]; UpTrend = 0; Sell[i] = 1; Short[i] = 1;
		}
	} else { // DownTrend
		if( UL[ i ] < trailstop ) trailstop = Min( trailstop, res[ i ] ); // UpTrend = 1;
		else {
			trailstop = sup[i]; UpTrend = 1; Buy[i] = 1; Cover[i] = 1;
		}
	}

	trailARRAY[ i ] = trailstop;
}

// remove part after first exit/cross between trailing stop and close
if (ParamToggle("Display Only First", "No|Yes")) {
	N = BarsSince(Start);
	NB = BarsSince(Buy); NS = BarsSince(Sell);
	NSS = BarsSince(Short); NC = BarsSince(Cover);
	LongTrade = (NB <= N) AND (NS < NB);
	ShortTrade = (NSS <= N) AND (NC < NSS);
	After = trailArray AND (LongTrade OR ShortTrade) ;
	trailArray = IIf(Ref(Flip(After, 0), -1), Null, trailArray); 
}

nextday = ParamToggle("Show Next Bar trailing Stop ?", "No|Yes", 1);
shift = 1-nextday;
trailArray = IIf(Started, Ref(trailArray,-shift), Null);


PlotShapes(Buy*shapeUpArrow,colorGreen,0,trailarray);
PlotShapes(Sell*shapeDownArrow,colorRed,0,trailarray);

Plot( Close,"Price",colorBlack,styleBar);
color = Ref(IIf(Flip(Buy,Sell), colorGreen, IIf(Flip(Sell,Buy), colorRed, colorDefault)),-1);
Plot( trailARRAY,"trailing stop level", color, styleThick );

Regards

3 Likes

Hello all,

I had done some work a while ago with what is believe is similar to what you are asking (maybe?)

I never too much time on trying to improve it beyond it's current state but if anyone can improve it please be nice and share :grin:

It is mean as a "trade management" tool and I use it as a pane rather than main chart.

Code and screenshot example below :point_down:

image

_SECTION_BEGIN("WIP");

//general
_N(Title="");
EnableTextOutput(False);
RequestTimedRefresh(0.1);

//definitions
num_Cost=1;
num_Stop=2;
num_Date=4;
num_Enter=3;
num_Clear=5;
output_Cost=0;
output_Stop=0;
output_1R=0;
output_Date="";

//enter cost
GfxTextOut("Enter your Cost",5,12);
GuiEdit(num_Cost,120,10,120,25,100);
input_Cost=GuiGetText(num_Cost);

//enter stop
GfxTextOut("Initial Stop",5,42);
GuiEdit(num_Stop,120,40,120,25,100);
input_Stop=GuiGetText(num_Stop);

//enter date
GfxTextOut("Date Bought",5,72);
GuiEdit(num_Date,120,70,120,25,100);
input_Date=GuiGetText(num_Date);

//create buttons
GuiButton("Enter",num_Enter,300,10,100,30,7);
GuiButton("Clear",num_Clear,300,40,100,30,7);

//check if you have already done this symbol
CheckLog=StaticVarGet("Log_"+Name(),True);

if (Name()!=StaticVarGetText("Previous")) { 
// did the symbol change?
	if (CheckLog==1) { 
		// if already done this symbol load the data
		GuiSetText(""+StaticVarGet("output_Cost_"+Name(),True),num_Cost);
		GuiSetText(""+StaticVarGet("output_Stop_"+Name(),True),num_Stop);
		GuiSetText(""+StaticVarGetText("output_Date_"+Name()),num_Date);
	}
	else { 
		// if not then make sure the guiedit is empty
		GuiSetText("",num_Cost);
		GuiSetText("",num_Stop);
		GuiSetText("",num_Date);
	}
}

// set staticvar as the current symbol
StaticVarSetText("Previous",Name());

//detect clicks
ID=GuiGetEvent(0,0);
EV=GuiGetEvent(0,1);

if (ID==num_Enter && EV ==1) { 
	//enter click loads all the staticvars
	StaticVarSet("Log_"+Name(),1,True);
	StaticVarSet("output_Cost_"+Name(),StrToNum(input_Cost),True);
	StaticVarSet("output_Stop_"+Name(),StrToNum(input_Stop),True);
	StaticVarSetText("output_Date_"+Name(),input_Date,True);	
}

if (ID==num_Clear && EV ==1) { 
	//clear button clears symbols' vars
	StaticVarSet("Log_"+Name(),0,True);
	StaticVarRemove("output_Cost_"+Name());
	StaticVarRemove("output_Stop_"+Name());
	StaticVarRemove("output_Date_"+Name());
}

if (CheckLog==1) { 

	output_Date=StaticVarGetText("output_Date_"+Name());
	output_Cost=StaticVarGet("output_Cost_"+Name(),True);
	output_Stop=StaticVarGet("output_Stop_"+Name(),True);
	
	BuyBI=Lookup(BarIndex(),StrToDateTime(output_Date),0); // find the barindex that corresponds to the buy date
	StartBI=BuyBI-10; // start plotting 10 days before that

	// scale the chart to fill the pane
	ScaleMin=LastValue(LLV(L-ATR(10),BarIndex()-StartBI),True);
	ScaleMax=LastValue(HHV(H+ATR(10),BarIndex()-StartBI),True);
	SetChartOptions(1,chartLogarithmic,chartGridMiddle,ScaleMin,ScaleMax);

	// plot the price, MA, cost, stop etc.
	Plot(IIf(BarIndex()>StartBI,Close,Null),"",colorBlack,styleBar);
	Plot(IIf(BarIndex()>StartBI,MA(C,10),Null),"",colorRed);
	Plot(IIf(BarIndex()>=BuyBI,output_Cost,Null),"",colorGreen,styleDashed|styleThick);
	Plot(IIf(BarIndex()>=BuyBI,output_Stop,Null),"",colorRed,styleDashed|styleThick);
	PlotShapes((BarIndex()==BuyBI)*shapeUpArrow,colorGreen,0,Low);

	//1R
	output_1R=100*((output_Stop-output_Cost)/output_Cost);
	PlotText(""+NumToStr(abs(output_1R),1.1,False)+"%",LastValue(BarIndex(),True)+2,LastValue((output_Stop+output_Cost)/2,True),colorBlack,colorWhite,-5);

	//profit
	CurProfit=100*((Close-output_Cost)/output_Cost);
	PlotText(""+NumToStr(CurProfit,1.1,False)+"%",LastValue(BarIndex(),True)+2,LastValue(High,True),colorBlack,colorWhite);

	//days since buy
	sinceBuy=BarIndex()-BuyBI+1;
	PlotShapes(Cross(sinceBuy,7)*shapeSmallCircle,colorBlue,0,High);

	//average cross above cost
	crossAvg=Cross(MA(C,10),output_Cost);
	PlotShapes(crossAvg*shapeSmallCircle,colorRed,0,Low);

	//expectancy
	multiple1R=CurProfit/abs(output_1R);
	PosExpectancy=Cross(multiple1R,2);
	PlotShapes(PosExpectancy*shapeSmallCircle,colorGreen,0,High,5);

	//drawdown
	top=HHV(H,sinceBuy)*(1-2*(abs(output_1R/100)));
	Plot(IIf(BarIndex()>BuyBI,Ref(top,-1),Null),"",colorLightGrey,styleThick);


	timeSignal=WriteIf(sinceBuy>=7 AND CurProfit<abs(output_1R),"* consider trimming","");
	
	GfxTextOut( "Days = "	+ NumToStr( sinceBuy, 1, False ) + timeSignal		, 500, 10 );
	GfxTextOut( "1R = " 	+ NumToStr( abs( output_1R ), 1.2, False ) + "%"	, 500, 30 );
	GfxTextOut( "Profit = " + NumToStr( CurProfit, 1.2, False ) + "% (" + NumToStr( multiple1R, 1.2, False ) + "x1R)", 500, 50 );

}

if (Status("action")==actionExplore) { 
// run this only on the favorites

	Filter=CheckLog==1;

	AddColumn(output_Cost,"output_Cost",1.2,colorBlack,colorWhite,100);
	AddColumn(output_Stop,"output_Stop",1.2,colorBlack,colorWhite,100);
	AddColumn(output_1R,"output_1R",1.2,colorBlack,colorWhite,100);
	AddColumn(Close,"Close",1.2,colorBlack,colorWhite,100);
	AddColumn(MA(Close,10),"MA10",1.2,colorBlack,colorWhite,100);

}
_SECTION_END();```
2 Likes

Thanks for all your ideas, I learned a lot about AB by going through them.

  John

That is rather unfair comment. It is easily achievable as shown above. AmiBroker is PROGRAMMABLE platform. Everything in AmiBroker is realizable by means of formula. That is its strength and flexibility. It is not locked to single or two hard coded stop types.
There are dozens of possible ways of "trailing stop". So you surely don't want the program's UI to be bloated with dozens of options to scroll thru. Instead of hard coding, you use the formula that implements what you are after. @portfoliobuilder pointed you to ready-to-use solution that was given in the members' zone.

There is also trailing stop drawing code in the Knowledge Base.

Tomasz,

I have been in this business for 42 years. I started on microcomputers and used the CP/M OS and SuperCalc to create Bollinger Bands. I have used nearly every major TA platform from TradeCenter and CompuTrac to TrendSpider and TradingView. I have learned many platform languages from Easy Language to Pine. So if anybody out there is qualified to comment on what he thinks ought to be available on a TA platform it is likely to be me. But hold one, before you get too prickly with me, please remember that I was an early adopter of AB, have championed AB widely, and that my recommendations are responsible for a decent chunk of your user base.

Do I think that the ability to plot a mainline trailing stop like a Chandelier or Parabolic should be part of the core functionality of any TA platform? You bet I do! And I don't think that I should have to spend a couple of hours figuring out the intricacies of a platform to do so.

Many thanks to the many kind AB users who have helped me along my way!

Unrepentantly,

 John Bollinger, CFA, CMT

Actually, that does not solve my request, that plots a Chandelier stop and reverse system.

FYI: Chandeliers and Parabolic stops are INCLUDED as core functionality.

SAR
http://www.amibroker.com/guide/afl/sar.html

Chandelier (see ApplyStop example)
http://www.amibroker.com/guide/afl/applystop.html

and Traders Tips code that I WROTE and @portfoliobuilder just pointed out to you plots Stop STARTING FROM selected date, exactly as you asked for in first post:

For something super-simple see this:

StartDate = ParamDate("Start Date", "" );
StopAmount = Param("Amount $", 1, 0.01, 10, 0.01);

// fixed dollar amount stop (from highest high since entry)
StopLine = HighestSince( StartDate == DateNum(), High) - StopAmount;
StopLineTriggered = Flip( StopLine > Close, 0 ); // close triggering

StopLine = IIf( StopLineTriggered, Null, StopLine ); // draw only until triggered once

Plot( Close, "Price", colorDefault, styleLine );
Plot( StopLine, "StopLine", colorBlue | styleThick );`

or I don't understand what you are after.

1 Like

Mea culpa, I should have posted a couple of illustrations to start.
aapl-stop
spy-stop

Apologies,

 John
1 Like

image
here is the required AFL code

SetBarsRequired( sbrAll, 0 );
RequestTimedRefresh( 1, False );
Setchartoptions( 0, Chartshowarrows | chartShowDates );
Plot( C, "Close", colorDefault, styleNoTitle | GetPriceStyle() );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );


Entry_Date = ParamDate( "Entry Date", "2022-06-21", 2 );
stopType = ParamList( "Name", "parabolic|chandelier", 1 );
chandMult = Param( "Chand Mult", 3, 1, 5, 1 );
chandLength = Param( "Chand Length", 10, 5, 50, 1 );
paraAccel = Param( "Para Accel", 0.02, 0.01, 0.1, 0.01 );
paraMax = Param( "para Max", 0.2, 0.1, 0.5, 0.01 );


Entry_Date_Text = DateTimeFormat( "%a %d %b %Y  ", Entry_Date );
Entry_Date_DateTime = Lookup( DateTime(), Entry_Date, 1 );

Buy = DateTime() == Entry_Date_DateTime;
BuyPrice = Close;

if( stopType == "chandelier" )
{
    Buy_TSL_Point = Ref( ATR( chandLength ), -1 ) * chandMult;
    Short_TSL_Point = Ref( ATR( chandLength ), -1 ) * chandMult;
}
else
    if( stopType == "parabolic" )
    {
        Buy_TSL_Point = abs( Ref( Close, -1 ) - Ref( SAR( paraAccel, paraMax ), -1 ) );
        Short_TSL_Point = abs( Ref( Close, -1 ) - Ref( SAR( paraAccel, paraMax ), -1 ) );
    }

Sell = 0;

In_LongTrade = In_ShortTrade = 0;

Buy_Price = Short_Price = 0;
Buy_TSLPrice = Short_SLPrice = Short_TSLPrice = 0;

Plot_BuyPrice = Plot_ShortPrice = Null;
Plot_Buy_TSL = Plot_Short_TSL = Plot_Buy_TSL = Plot_Short_TSL = Null;
Highest_Since_Buy = Lowest_Since_Buy = 0;



for( i = 1; i < BarCount; i++ )
{

    if( In_LongTrade == 0 AND Buy[ i ] )
    {
        In_LongTrade = 1;
        Buy[ i ] = 1;
        Buy_Price = BuyPrice[i];
        Highest_Since_Buy = High[i];
        Buy_TSLPrice = Buy_Price - Buy_TSL_Point[i];

    }
    else Buy[ i ] = 0;


    if( In_LongTrade )
    {

        if( High[ i] > Highest_Since_Buy[ i - 1 ] AND !Buy[i] )
            Highest_Since_Buy[ i ] = High[ i ] ;
        else
            if( Highest_Since_Buy[ i - 1 ] > 0 )
                Highest_Since_Buy[ i ] = Highest_Since_Buy[ i - 1 ];


        if( Buy_TSLPrice[i] > 0 AND !Buy[i] )
        {
            if( ( Highest_Since_Buy[i - 1] - Buy_TSL_Point[i] ) > Buy_TSLPrice[i - 1] )
            {
                Buy_TSLPrice[i] = Highest_Since_Buy[i - 1] - Buy_TSL_Point[i];
            }
            else Buy_TSLPrice[i] = Buy_TSLPrice[i - 1];
        }

        Plot_BuyPrice[i] = Buy_Price;


        if( Buy_TSLPrice[i] > 0 )
        {
            Plot_Buy_TSL[i] = Buy_TSLPrice[i];
        }

        if( Low[ i ] < Buy_TSLPrice[ i ] AND Buy_TSLPrice[ i ] > 0 )
        {
            Sell[ i ] = 1;
            SellPrice[i] = Min( Buy_TSLPrice[ i ], Open[i] );
            Buy_Price =  Buy_TSLPrice = In_LongTrade = 0;
        }

    }


}

PlotShapes( IIf( Buy, shapeSquare, shapeNone ), colorGreen, 0, L, Offset = -15 );
PlotShapes( IIf( Buy, shapeSquare, shapeNone ), colorLime, 0, L, Offset = -25 );
PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), colorWhite, 0, L, Offset = -20 );

PlotShapes( IIf( Sell, shapeSquare, shapeNone ), colorRed, 0, H, Offset = 15 );
PlotShapes( IIf( Sell, shapeSquare, shapeNone ), colorOrange, 0, H, Offset = 25 );
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorWhite, 0, H, Offset = -20 );

_SECTION_BEGIN( "Show Text" );
Price_Level_Para = ParamToggle( "Show Text", "No|Yes", 0 );
Price_Distance_Para = 0.12; // Param( "Price Distance", 0.12, 0.01, 0.5, 0.01 );
_SECTION_END();


Visible_HL_Diffrenece = HighestVisibleValue( High ) - LowestVisibleValue( Low );
Distance_From_HL = Visible_HL_Diffrenece * Price_Distance_Para;

if( Price_Level_Para )
{
    for( i = 0; i < BarCount; i++ )
    {

        if( Buy[i] ) PlotText( "Entry = " + BuyPrice[i], i, L[ i ] - Distance_From_HL[i], colorBlack, colorLime );

        if( Plot_Buy_TSL[i] AND Sell[i] ) PlotText( StrFormat( "\nTSL(%g) = ", Prec( Buy_TSL_Point[i], 2 ) ) + Prec( Plot_Buy_TSL[i], 2 ), i, L[ i ] - Distance_From_HL[i], colorBlack, colorLime );

        if( Buy[i] ) PlotText( Entry_Date_Text, i, L[ i ] - Distance_From_HL[i] * 2,  colorWhite, colorBlue );

    }
}

Plot( Plot_BuyPrice , WriteIf( Plot_BuyPrice > 0, "\n\n Buy Price", "" ), colorBrightGreen, styleLine );
Plot( Plot_Buy_TSL, WriteIf( Plot_Buy_TSL > 0, "\n Long TSL", "" ), colorOrange, styleLine | styleDashed );
4 Likes

Why are you re-inventing the wheel by over complicated loop code?
Simply look at AmiBroker KB.

Below one is doing same as upper one without thousand if-else statements and unnecessary subscripting.

Sell = 0; 
Buy_TSLPrice = 0;
Plot_Buy_TSL = Null;
Highest_Since_Buy = 0;

for( i = 0; i < BarCount; i++ )
{
    if( Buy_TSLPrice == 0 AND Buy[ i ] )
    {
        Buy[ i ] = 1;
        Highest_Since_Buy = High[i];
        Buy_TSLPrice = BuyPrice[i] - Buy_TSL_Point[i];
    }
    else Buy[ i ] = 0;
    

    if( Buy_TSLPrice > 0 )
    {
		if ( !Buy[i] ) {
			hh = Highest_Since_Buy - Buy_TSL_Point[i];			
			Buy_TSLPrice = Max(hh, Buy_TSLPrice); 
			Highest_Since_Buy = Max(High[ i ], Highest_Since_Buy);
        } 
  
		Plot_Buy_TSL[i] = Buy_TSLPrice[i];

		if( Low[ i ] < Buy_TSLPrice[ i ]  )
		{
			Sell[ i ] = 1;
			SellPrice[i] = Min( Buy_TSLPrice[ i ], Open[i] );
			Buy_TSLPrice = 0;
		}		
    }
}

And instead of this

Just write this (so you do not need just another Plot_BuyPrice varaible inside loop as you did).

Plot( IIf(Plot_Buy_TSL>0,Valuewhen(Buy,BuyPrice), Null), WriteIf( Plot_Buy_TSL > 0, "\n\n Buy Price", "" ), colorBrightGreen, styleLine );
1 Like

Why using endless of Ref functions in single line using same Ref period?
Ref() works on entire array for single line of same period!

So all that is needed is this

Buy_TSL_Point = abs( Ref( Close - SAR( paraAccel, paraMax ), -1 ) );
        Short_TSL_Point = abs( Ref( Close - SAR( paraAccel, paraMax ), -1 ) );

Thanks for the suggestion. will implement on next coding...

1 Like

Thank for the guide. Rewritten the above code as below. Learn the new way to TSL coding..

SetBarsRequired( sbrAll, 0 );
RequestTimedRefresh( 1, False );
Setchartoptions( 0, Chartshowarrows | chartShowDates );
Plot( C, "Close", colorDefault, styleNoTitle | GetPriceStyle() );
_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ) );


Entry_Date = ParamDate( "Entry Date", "2022-06-21", 2 );
stopType = ParamList( "Name", "parabolic|chandelier", 1 );
chandMult = Param( "Chand Mult", 3, 1, 5, 1 );
chandLength = Param( "Chand Length", 10, 5, 50, 1 );
paraAccel = Param( "Para Accel", 0.02, 0.01, 0.1, 0.01 );
paraMax = Param( "para Max", 0.2, 0.1, 0.5, 0.01 );


Entry_Date_Text = DateTimeFormat( "%a %d %b %Y  ", Entry_Date );
Entry_Date_DateTime = Lookup( DateTime(), Entry_Date, 1 );

Buy = DateTime() == Entry_Date_DateTime;
BuyPrice = Close;

if( stopType == "chandelier" )
{
    Buy_TSL_Point = Ref( ATR( chandLength ), -1 ) * chandMult;
    Short_TSL_Point = Ref( ATR( chandLength ), -1 ) * chandMult;
}
else
    if( stopType == "parabolic" )
    {
        Buy_TSL_Point = abs( Ref( Close - SAR( paraAccel, paraMax ), -1 ) );
        Short_TSL_Point = abs( Ref( Close - SAR( paraAccel, paraMax ), -1 ) );
    }

Sell = 0;
Buy_TSLPrice = 0;
Plot_Buy_TSL = Null;
Highest_Since_Buy = 0;

for( i = 0; i < BarCount; i++ )
{
    if( Buy_TSLPrice == 0 AND Buy[ i ] )
    {
        Buy[ i ] = 1;
        Highest_Since_Buy = High[i];
        Buy_TSLPrice = BuyPrice[i] - Buy_TSL_Point[i];
    }
    else Buy[ i ] = 0;


    if( Buy_TSLPrice > 0 )
    {
        if( !Buy[i] )
        {
            hh = Highest_Since_Buy - Buy_TSL_Point[i];
            Buy_TSLPrice = Max( hh, Buy_TSLPrice );
            Highest_Since_Buy = Max( High[ i ], Highest_Since_Buy );
        }

        Plot_Buy_TSL[i] = Buy_TSLPrice[i];

        if( Low[ i ] < Buy_TSLPrice[ i ] )
        {
            Sell[ i ] = 1;
            SellPrice[i] = Min( Buy_TSLPrice[ i ], Open[i] );
            Buy_TSLPrice = 0;
        }
    }
}

PlotShapes( IIf( Buy, shapeSquare, shapeNone ), colorGreen, 0, L, Offset = -15 );
PlotShapes( IIf( Buy, shapeSquare, shapeNone ), colorLime, 0, L, Offset = -25 );
PlotShapes( IIf( Buy, shapeUpArrow, shapeNone ), colorWhite, 0, L, Offset = -20 );

PlotShapes( IIf( Sell, shapeSquare, shapeNone ), colorRed, 0, H, Offset = 15 );
PlotShapes( IIf( Sell, shapeSquare, shapeNone ), colorOrange, 0, H, Offset = 25 );
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorWhite, 0, H, Offset = -20 );

_SECTION_BEGIN( "Show Text" );
Price_Level_Para = ParamToggle( "Show Text", "No|Yes", 1 );
Price_Distance_Para = 0.12; // Param( "Price Distance", 0.12, 0.01, 0.5, 0.01 );
_SECTION_END();


Visible_HL_Diffrenece = HighestVisibleValue( High ) - LowestVisibleValue( Low );
Distance_From_HL = Visible_HL_Diffrenece * Price_Distance_Para;

if( Price_Level_Para )
{
    for( i = 0; i < BarCount; i++ )
    {
        if( Buy[i] ) PlotText( "Entry = " + BuyPrice[i], i, L[ i ] - Distance_From_HL[i], colorBlack, colorLime );

        if( Plot_Buy_TSL[i] AND Sell[i] ) PlotText( StrFormat( "\nTSL(%g) = ", Prec( Buy_TSL_Point[i], 2 ) ) + Prec( Plot_Buy_TSL[i], 2 ), i, L[ i ] - Distance_From_HL[i], colorBlack, colorLime );

        if( Buy[i] ) PlotText( Entry_Date_Text, i, L[ i ] - Distance_From_HL[i] * 2,  colorWhite, colorBlue );

    }

}

Plot( Plot_Buy_TSL, WriteIf( Plot_Buy_TSL > 0, "\n Long TSL", "" ), colorOrange, styleLine | styleDashed );


4 Likes

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.