using System; using System.Collections.Generic; using System.Text; using System.Drawing; using WealthLab; using WealthLab.Indicators; using TASCIndicators;namespace WealthLab.Strategies { /* MFO divergence: Price sets a lowest low but the indicator fails to confirm the new low and turns up */ public class MFO_Divergence : WealthScript { private StrategyParameter paramHighest; private StrategyParameter paramPeriod; public MFO_Divergence() { paramPeriod = CreateParameter("MFO period", 20, 2, 100, 1); paramHighest = CreateParameter("Highest high of", 20, 5, 50, 1); } protected override void Execute() { bool peak = false; int peakBar = -1; int high = paramHighest.ValueInt; bool trough = false; int troughBar = -1; int low = paramHighest.ValueInt; int period = paramPeriod.ValueInt; MoneyFlowOscillator mfo = MoneyFlowOscillator.Series( Bars, period ); Lowest indicatorLowest = Lowest.Series( mfo, low ); Lowest hLow = Lowest.Series( Low, low ); HideVolume(); LineStyle solid = LineStyle.Solid; ChartPane mfoPane = CreatePane( 50, false, true ); PlotSeries( mfoPane, mfo, Color.Green, solid, 2 ); DrawHorzLine( mfoPane,0,Color.Blue,LineStyle.Dashed,1); for(int bar = GetTradingLoopStartBar(period); bar < Bars.Count; bar++) { if (!IsLastPositionActive) { /* 1st peak: both price and indicator */ if( peak == false ) { if( ( High[bar-1] == Highest.Series( High, high )[bar-1] ) & ( mfo[bar-1] == Highest.Series( mfo, high )[bar-1] ) & TurnDown( bar, High ) & TurnDown( bar, mfo ) ) { peak = true; peakBar = bar-1; } } if( peak == true ) { if( ( High[bar] != Highest.Series( High, high )[bar] ) & ( mfo[bar] == Highest.Series( mfo, high )[bar] ) ) peak = false; } /* 2nd peak: price high not confirmed by the indicator */ if( peak == true ) { if( ( High[bar-1] == Highest.Series( High, high )[bar-1] ) & ( High[bar-1] >= High[peakBar] ) & ( mfo[bar-1] != Highest.Series( mfo, high )[bar-1] ) & ( mfo[bar-1] < mfo[peakBar] ) & TurnDown( bar, High ) & TurnDown( bar, mfo ) ) { peak = false; /* Shorting doesn't work well */ // Fade the trend // if( mfo[bar] > 0 ) // if( ShortAtMarket( bar+1 ) != null ) // LastPosition.Priority = Close[bar]; /* Highlight divergence */ for (int b = peakBar; b <= bar; b++) SetPaneBackgroundColor( mfoPane, b, Color.FromArgb( 30, Color.LightCoral ) ); DrawLine( PricePane, peakBar, High[peakBar], bar-1, High[bar-1], Color.Red, solid, 2 ); DrawLine( mfoPane, peakBar, mfo[peakBar], bar-1, mfo[bar-1], Color.Blue, solid, 2 ); } } /* 1st trough: both price and indicator */ if( trough == false ) { if( ( Low[bar-1] == Lowest.Series( Low, low )[bar-1] ) & ( mfo[bar-1] == Lowest.Series( mfo, low )[bar-1] ) & TurnUp( bar, Low ) & TurnUp( bar, mfo ) ) { trough = true; troughBar = bar-1; } } if( trough == true ) { if( ( Low[bar] != Lowest.Series( Low, low )[bar] ) & ( mfo[bar] == Lowest.Series( mfo, low )[bar] ) ) trough = false; } /* 2nd trough: price low not confirmed by the indicator */ if( trough == true ) { if( ( Low[bar-1] == Lowest.Series( Low, low )[bar-1] ) & ( Low[bar-1] <= Low[troughBar] ) & ( mfo[bar-1] != Lowest.Series( mfo, low )[bar-1] ) & ( mfo[bar-1] > mfo[troughBar] ) & TurnUp( bar, Low ) & TurnUp( bar, mfo ) ) { trough = false; /* Fade the trend */ if( mfo[bar] < 0 ) if( BuyAtMarket( bar+1 ) != null ) LastPosition.Priority = -Close[bar]; /* Highlight divergence */ for (int b = troughBar; b <= bar; b++) SetPaneBackgroundColor( mfoPane, b, Color.FromArgb( 30, Color.LightGreen ) ); DrawLine( PricePane, troughBar, Low[troughBar], bar-1, Low[bar-1], Color.Blue, solid, 2 ); DrawLine( mfoPane, troughBar, mfo[troughBar], bar-1, mfo[bar-1], Color.Red, solid, 2 ); } } } else { Position p = LastPosition; if( p.PositionType == PositionType.Long ) { if( CrossOver(bar, mfo, 0) ) ExitAtMarket( bar+1, p, "MFO Crossover" ); } else if( CrossUnder(bar, mfo, 0) ) ExitAtMarket( bar+1, p, "MFO Crossunder" ); } } } } }