Syntax
public ATRModified(Bars ds, int period, string description)
public static ATRModified Series(Bars ds, int period)
Parameter Description
ds |
The source Bars object |
period |
The indicator period. |
Description
The ATRModified (Modified ATR) indicator from the June 2009 issue of
Stocks & Commodities magazine. Vervoot modified Wilder's True Range calculation to smooth out the result so that a single highly volatile day has less influence than before. Specifically, the current High minus Low component is limited to 150% of it's simple moving average, and, gap influence is limited to half the value of the current high minus the previous close.
The MetaStock code for these ideas in the article was presented as follows. See the TASCIndicators Open Source for our Wealth-Lab solution.
HiLo:=If(H-L<1.5 * Mov(H-L,period,S),H-L, 1.5 * Mov(HL,period,S));
Href:=If(L<=Ref(H,-1),H-Ref(C,-1),(H-Ref(C,-1))-(L-Ref(H,-1))/2);
Example
/* WealthScript from June 2009 Traders' Tip. Requires TASCIndicators 1.0.7.0 (or higher) */
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
namespace WealthLab.Strategies
{
/* Class that encapsulates the ATR Trailing Stop, closing basis */
public class ATRTrail
{
private WealthScript ws;
private Bars bars;
private double stopPrice;
private bool longPosition;
private DataSeries atrMod;
public ATRTrail(WealthScript wL, Bars b, bool positionLong, double initialStop, int period, double factor )
{
ws = wL;
bars = b;
longPosition = positionLong;
stopPrice = initialStop;
atrMod = factor * TASCIndicators.ATRModified.Series(bars, period);
}
// Call this method to update and return the stop price on each bar after entry
public double Price(int bar)
{
double prevPrice = stopPrice;
double newPrice;
if (longPosition)
{
newPrice = bars.Close[bar] - atrMod[bar];
stopPrice = newPrice > stopPrice ? newPrice : stopPrice;
}
else
{
newPrice = bars.Close[bar] + atrMod[bar];
stopPrice = newPrice < stopPrice ? newPrice : stopPrice;
}
ws.DrawLine(ws.PricePane, bar-1, prevPrice, bar, stopPrice, Color.Blue, LineStyle.Solid, 1);
return stopPrice;
}
}
public class SAC_ATRTrailingStops : WealthScript
{
private StrategyParameter _isLong = null;
private StrategyParameter _initStop = null;
private StrategyParameter _period = null;
private StrategyParameter _atrMult = null;
private StrategyParameter _y = null;
private StrategyParameter _m = null;
private StrategyParameter _d = null;
public SAC_ATRTrailingStops()
{
_isLong = CreateParameter("Long = 1", 1, 0, 1, 1);
_initStop = CreateParameter("Initial Stop", 1.0, 0.25, 50.0, 0.25);
_period = CreateParameter("ATR Period", 5, 2, 100, 1);
_atrMult = CreateParameter("ATR Multiplier", 3.5, 1.0, 5.0, 0.1);
_m = CreateParameter("Month", 4, 1, 12, 1);
_d = CreateParameter("Day", 13, 1, 31, 1);
_y = CreateParameter("Year", 2009, 1990, 2012, 1);
}
/* Execute a strategy - trade on a specified date */
protected override void Execute()
{
DateTime dt;
try {
dt = new DateTime(_y.ValueInt, _m.ValueInt, _d.ValueInt);
}
catch {
DrawLabel(PricePane, "Invalid Date", Color.Red);
return;
}
int b = Bars.ConvertDateToBar(dt, false);
if (b < 1) {
DrawLabel(PricePane, "Date does not exist on chart", Color.Red);
return;
}
if( _isLong.ValueInt == 1 )
BuyAtMarket(b, "Discretionary");
else
ShortAtMarket(b, "Discretionary");
Position p = LastPosition;
// After creating a position, initialize a stop object
ATRTrail atrStop = new ATRTrail(this, Bars, p.PositionType == PositionType.Long, _initStop.Value, _period.ValueInt, _atrMult.Value);
for(int bar = b + 1; bar < Bars.Count; bar++)
{
if (p.Active)
{
if (p.PositionType == PositionType.Long)
{
if( Close[bar] < atrStop.Price(bar) )
ExitAtMarket(bar + 1, p);
}
else if( Close[bar] > atrStop.Price(bar) )
ExitAtMarket(bar + 1, p);
}
}
}
}
}