Traders' Tip text
In the ongoing battle between high frequency trading and sky-high I.Q. algorithms, on the scene filled with discretionary chart patterns and advanced indicators doing heavy number crunching under the hood, Konner's systematic approach stands out as an isle of clarity and simplicity.
The concept of trading corrections in a downtrend is like having a second system blended together, potentially helping smooth overall performance. In our test on a portfolio of the Dow 30 stocks over the last 10 years with 5% of portfolio equity allocated to each position, the system was profitable and its returns exceeded Buy&Hold's net profit. However, trading corrections accounted for slightly more than 6% of all entry signals (6 out of 91).
Figure 1. The equity curve of the system applied to a portfolio of the Dow 30 stocks.
The system is designed to trade weekly bars, and the average trade in this portfolio is held for over a year. Time in market is another dimension of risk, and charting the “life” of a trade (Figure 2) shows that the majority of losing trades becomes losers from the start, or hang about the breakeven level for quite a long time. With this knowledge, a potential improvement could be introduced.
Figure 2. A Wealth-Lab Developer 6.0 chart showing the profit/loss of a single losing trade vs. the time in each trade (in weekly bars).
Considering this, we added a new, optional rule to the system:
- If after 20 (by default) weekly bars in trade, the position is still at its breakeven point or is losing money, close it at the open of the next bar (i.e. next Monday).
Ruling out low-probability trades with this simple tweak positively affected the net profit (62% vs. 56%) without increasing risk, and made the system tie up less capital in unproductive trades, reducing the average trade duration by the whole quarter.
To turn this extra rule on or off in Wealth-Lab 6, simply drag the parameter slider “Exit loser?” in the bottom left corner of the main workspace, and re-run the Strategy.
WealthScript Code (C#)
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
namespace WealthLab.Strategies
{
public class RSIwithRSI : WealthScript
{
private StrategyParameter paramLoser;
private StrategyParameter paramExit;
public RSIwithRSI()
{
paramLoser = CreateParameter("Exit loser?", 0, 0, 1, 1);
paramExit = CreateParameter("Exit loser after", 20, 2, 50, 2);
}
protected override void Execute()
{
DataSeries rsiSlow = RSI.Series(Close, 17);
DataSeries maSlow = SMA.Series(Close, 40);
DataSeries maFast = SMA.Series(Close, 10);
DataSeries rsiFast = RSI.Series(Close, 5);
ChartPane paneRSI = CreatePane(35,true,true);
PlotSeries(paneRSI, rsiSlow, Color.Blue, LineStyle.Solid, 2);
PlotSeries(paneRSI, rsiFast, Color.Red, LineStyle.Solid, 2);
DrawHorzLine(paneRSI, 60.00, Color.Green, LineStyle.Solid, 1);
DrawHorzLine(paneRSI, 40.00, Color.Red, LineStyle.Solid, 1);
PlotSeries(PricePane,maSlow,Color.Blue,LineStyle.Solid,2);
PlotSeries(PricePane,maFast,Color.Red,LineStyle.Solid,2);
for(int bar = GetTradingLoopStartBar(40); bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
Position p = LastPosition;
if( paramLoser.ValueInt == 1 &&
p.NetProfitAsOfBarPercent(bar) <= 0 &&
bar > p.EntryBar + paramExit.ValueInt )
SellAtMarket( bar+1, p, "Exit loser" );
if (p.EntrySignal.Contains("correction"))
{
if( (Close[bar] < maFast[bar]) &&
CrossUnder(bar, rsiFast, 40) )
SellAtMarket(bar + 1, p, "Correction sell");
}
else
{
if( (Close[bar] < maSlow[bar]) &&
CrossUnder(bar, rsiSlow, 40.00) )
SellAtMarket(bar + 1, p, "Trend sell");
}
}
else
{
if( ( rsiSlow[bar] < 40 ) && CrossOver(bar, rsiFast, 60.00) &&
(Close[bar] > maFast[bar]) )
if( BuyAtMarket(bar + 1, "correction") != null )
LastPosition.Priority = -Close[bar];
if (CrossOver(bar, rsiSlow, 60.00) &&
(Close[bar] > maSlow[bar]) )
if( BuyAtMarket(bar + 1, "trend") != null )
LastPosition.Priority = -Close[bar];
}
}
}
}
}