HomeKnowledge Base

Ruin stop or mysterious Short(6) in the trade list

When you back-test a trading system, you may sometimes encounter trades marked with (6) exit reason, showing e.g.: Short (6) or Short (ruin) in the trade list as in the picture below:

Ruin stop in trade list

As explained in the this Knowledge Base article: such identifier tells us that the trade was closed because of the ruin stop activation.

A ruin-stop is a built-in, fixed percentage stop set at -99.96%, so it gets activated if your position is losing almost all (99.96%) of its entry value. It almost never occurs in long trades, but it may be quite common if your trading system places short trades without any kind of maximum loss stop. Imagine that you short a stock when its price is $10, then it’s price rises to $20 (twice the entry price). When you buy to cover the position you must pay $20 per share, which means that your loss on this trade is $10 per share ($20-$10). This means 100% loss (as per entry value). If you placed such a trade with all your capital you would be bankrupt. That is why this stop is called “ruin stop”. Unfortunately, by the nature of short selling, the gains are limited to 100% (when stock price goes down to zero) but losses are virtually unlimited.

So what to do to prevent exits by ruin stop?

The best idea is to just place proper max. loss stop at much smaller percentage (such as 10% or 20%) depending on what your risk tolerance is, to limit drawdowns and decrease the chance of wiping your account down to zero.

If, for some weird reason, you want to turn OFF this built-in stop, you can do so using this code:

SetOption"DisableRuinStop"True );

but it is highly discouraged, because when you wipe your account down to zero (or even below zero) it makes no point to run back-test any further. Instead of disabling this feature you should place proper, tighter maximum loss stop.

How does risk-mode trailing stop work?

In addition to regular percent or point based stops, AmiBroker allows to define stop size as risk (stopModeRisk), which means that we allow only to give up certain percent of profit gained in given trade. The picture presented below visualizes a risk-mode trailing stop using 35% risk size. Since at the very beginning of the trade profits may be very low (and potentially triggering unwanted exits), this type of stop is best to use with validFrom argument, which allows to delay stop activation by certain number of bars.

The blue line on top represents highest high since entry, while red line shows the stop level calculation, yellow area shows the bars, where our stop has become active:

Risk-mode trailing stop

The above levels were calculated with the following code:

Buy DateNum() == 1140425// custom entry on a fixed date
Sell 0;
BuyPrice SellPrice close;

riskSize 35;
daysDelay 50;

ApplyStopstopTypeTrailingstopModeRiskriskSize1False0daysDelay );

priceAtBuy ValueWhenBuyBuyPrice );
highsinceBuy HighestSinceBuyHigh);
stoplevel priceAtBuy + ( highsinceBuy priceAtBuy) * (100-riskSize)/100;

PlotClose"Close"colorDefaultstyleBar );
Plotstoplevel"stop"colorRedstyleDashed );
PlothighsinceBuy"highsinceBuy"colorBluestyleDashed );
PlotpriceAtBuy"priceAtBuy"colorBluestyleDashed );
PlotBarsSinceBuy ) > daysDelay""ColorBlendcolorYellowcolorWhite,0.9), styleArea|styleOwnScale,0,1,0,-1);

PlotShapesIIfSellshapeDownArrowshapeNone), colorRed0High);

Using price levels with ApplyStop function

ApplyStop function by default requires us to provide stop amount (expressed in either dollar or percentage distance from entry price). Therefore, if we want to place stop at certain price level, then we need to calculate the corresponding stop amount in our code.

This example shows how to place stops at previous bar Low (for long trades) and previous bar High (for short trades).

Stop amount parameter is simply the distance between entry price and desired trigger price (exit point). For long trade it is entry price minus stop level, while for short trade it is trigger (exit) price minus entry price. Additionally we may check if calculated distance is at least 1-tick large. We can distinguish between long and short entry by checking if one of entry signals is present (if a Buy signal is active then it is long entry, otherwise short). We only need to take care about the fact that if we are using trade delays we need to get delayed Buy signal as shown in the code below:

TradeDelay 1// set it to 0 for no delays

SetTradeDelaysTradeDelayTradeDelayTradeDelayTradeDelay );
TickSize 0.01;

// sample entry rules
Buy CrossMACD(), Signal() );
Short CrossSignal(), MACD() );
Sell Cover 0// no other exit conditions, just stops

BuyPrice SellPrice ShortPrice CoverPrice Close;

// define stop level
stopLevelLong RefL, -); // use previous bar low
stopLevelShort RefH, -); // use previous bar high

// calculate stop amount
stopAmountLong BuyPrice stopLevelLong;
stopAmountShort stopLevelShort ShortPrice;

// make sure stop-amount is at least one tick
stopAmountLong MaxTickSizeBuyPrice stopLevelLong );
stopAmountShort MaxTickSizestopLevelShort ShortPrice );

// assign stop amount conditionally by checking if there is a Buy signal on given bar
IsLong RefBuy, -TradeDelay );
stopAmount IIfIsLongstopAmountLongstopAmountShort );
ApplyStopstopTypeLossstopModePointstopAmountTrue );

Stops priority in the default backtest procedure in AmiBroker

The order stops are triggered in the backtest is the following:
 – Fixed Ruin stop (loosing 99.96% of the starting capital)
 – Max. loss stop
 – Profit target stop
 – Trailing stop
 – N-bar stop* (see below)

In versions 4.61 and higher: you can decide if N-BAR stop has the lowest or the highest priority. (more…)