using System; using System.Collections.Generic; using System.Text; using System.Drawing; using WealthLab; using WealthLab.Indicators;namespace WealthLab.Strategies { public class Katsanos201412 : WealthScript { private StrategyParameter paramPoleTimeout; private StrategyParameter paramFlagTimeout; private StrategyParameter paramUptrendBeforePole; private StrategyParameter paramMinFlagDuration; private StrategyParameter paramMaxFlagDuration; private StrategyParameter paramSMAPeriod; private StrategyParameter paramInactivityStop; private StrategyParameter paramTimeout; private StrategyParameter paramPoleHeight; private StrategyParameter paramFlagHeight; private StrategyParameter paramProfitTarget; void DrawRectangle(int b1, int b2, double p1, double p2, Color c) { double[] rect = { b1, p1, b1, p2, b2, p2, b2, p1 }; DrawPolygon( PricePane, Color.Blue, c, LineStyle.Solid, 1, true, rect ); } public Katsanos201412() { paramPoleTimeout = CreateParameter("Pole Timeout", 23, 10, 50, 1); paramPoleHeight = CreateParameter("Pole Height", 5.5, 1.0, 10, 0.5); paramUptrendBeforePole = CreateParameter("Uptrend Before Pole", 70, 10, 100, 10); paramSMAPeriod = CreateParameter("SMA Period", 50, 10, 100, 5); paramFlagHeight = CreateParameter("Flag Height", 2.5, 0.5, 5.0, 0.5); paramFlagTimeout = CreateParameter("Flag Timeout", 15, 3, 30, 1); paramMinFlagDuration = CreateParameter("Min Flag Duration", 3, 3, 30, 1); paramInactivityStop = CreateParameter("Inactivity Stop", 70, 10, 100, 10); paramTimeout = CreateParameter("Timeout", 100, 10, 100, 10); paramProfitTarget = CreateParameter("Profit Target ATR", 1.2, 0.2, 3.0, 0.2); } protected override void Execute() { int PoleTimeout = paramPoleTimeout.ValueInt, FlagTimeout = paramFlagTimeout.ValueInt, UptrendLeadingToPole = paramUptrendBeforePole.ValueInt, MinFlagDuration = paramMinFlagDuration.ValueInt, smaPeriod = paramSMAPeriod.ValueInt, inactivityStop = paramInactivityStop.ValueInt, timeout = paramTimeout.ValueInt, PoleBar = 0, FlagBar = 0, ba = 0; double poleHeight = paramPoleHeight.Value, flagHeight = paramFlagHeight.Value, currPoleHeight = 0, ProfitTarget = paramProfitTarget.Value, InitialStop = 0, ws = 0.5, flagTop = 0, flagBottom = 0; bool PoleValid = false, FlagValid = false; SMA sma = SMA.Series( Close,smaPeriod ); LinearRegSlope lrs = LinearRegSlope.Series( Close, FlagTimeout ); HideVolume(); for(int bar = GetTradingLoopStartBar(100); bar < Bars.Count; bar++) { if (IsLastPositionActive) { // Exits Position p = LastPosition; double atr = ATR.Series( Bars, 40 )[bar]; double high = p.HighestHighAsOfBar(bar); double chandelier = high - atr * 3; double inactivity = atr * 4; if( ( bar+1 - p.EntryBar >= inactivityStop ) && ( p.MFEAsOfBar( bar ) < inactivity ) ) SellAtMarket( bar+1, p, "Inactivity+MFE" ); else if( bar+1 - p.EntryBar >= timeout ) SellAtMarket( bar+1, p, "Time exit" ); else if( !SellAtStop( bar+1, p, p.RiskStopLevel, "Stop loss" ) ) if( !SellAtStop( bar+1, p, chandelier, "Trailing (Chandelier)" ) ) SellAtLimit( bar+1, p, p.AutoProfitLevel, "Profit Target" ); } else { if( !PoleValid ) { //Uptrend during the last 70 bars leading to the pole. if(Lowest.Value( bar, Close, PoleTimeout ) > Lowest.Value( bar, Close, UptrendLeadingToPole )) { //A steep pole of 5.5 times the average true range (ATR) or more, in 23 bars or less. currPoleHeight = Close[PoleBar] - Close[bar - PoleTimeout]; double atr = ATR.Value(bar, Bars, 40); PoleBar = bar; PoleValid = currPoleHeight >= atr * poleHeight ? true: false; } } if( PoleValid ) { if( !FlagValid ) { //A flag breaking out in 15 bars or less from the pole top and sloping horizontally or slightly down. if( bar <= PoleBar + FlagTimeout && bar >= PoleBar + MinFlagDuration ) // To avoid premature triggering { flagTop = Highest.Value( bar, Close, FlagTimeout ); flagBottom = Lowest.Value( bar, Close, FlagTimeout ); InitialStop = flagBottom; double flagRange = flagTop - flagBottom; double atr = ATR.Value(bar, Bars, 40); double slope = lrs[bar]; bool isSlopeOK = slope > -0.04 && slope <= 0.01; //Flag depth not more than 2.5 times the ATR measured from the highest to the lowest point in the flag. if( flagRange <= atr * flagHeight && isSlopeOK ) { FlagValid = true; FlagBar = bar; } } else PoleValid = bar + 1 - PoleBar < PoleTimeout; // reset if Setup has timed out } if( FlagValid ) { if( BuyAtStop( bar + 1, Highest.Value(bar, High, FlagTimeout) ) != null ) { // Draw flag and pole DrawRectangle( FlagBar, FlagBar-FlagTimeout, flagTop, flagBottom, Color.LightSteelBlue ); DrawRectangle( PoleBar, PoleBar-PoleTimeout, Close[PoleBar], Close[PoleBar-PoleTimeout], Color.Transparent ); // Assign initial stop and profit target levels LastPosition.AutoProfitLevel = LastPosition.EntryPrice + currPoleHeight * ProfitTarget; LastPosition.RiskStopLevel = InitialStop; PoleValid = false; FlagValid = false; // reset Setup variables } else // reset if Setup has timed out { PoleValid = bar + 1 - PoleBar < PoleTimeout; FlagValid = false; flagTop = 0; flagBottom = 0; } } } } } } } }