Unit UpCandles; Interface Implementation Uses DataNodes, GenericDataNodes, StandardCandles, StandardPlaceHolders; Type TUpCandles = Class(TGenericDataNode) Private CandleData : TStandardCandles; FValid : Boolean; FValue : Integer; PreviousEpoch : Cardinal; Procedure VerifyCurrent; Public Function IsValid : Boolean; Override; Protected Constructor Create(Params : TParamList); Override; Published Function GetInteger : Integer; Override; End; Procedure TUpCandles.VerifyCurrent; Var Candles : TCandleArray; Type TDirection = (dEnd, { Not enough data to make a comparison. If we run out of data before we have an answer, then we don't know the answer. Our output cannot be valid. } dUp, { This candle is higher than the previous one. } dDown, { This candle is lower than the previous one. } dNeither); { This candle is not clearly above or below. } Function DescribeCandle(I : Integer) : TDirection; { I=0 compares the last candle to the previous one. I=1 compares the second to last candle to the one before that. etc. } Var Former, Latter : Integer; Begin { DescribeCandle } Latter := Pred(Length(Candles)) - I; Former := Pred(Latter); If Former < 0 Then Result := dEnd Else If (Candles[Latter].High > Candles[Former].High) And (Candles[Latter].Low > Candles[Former].Low) Then Result := dUp Else If (Candles[Latter].High < Candles[Former].High) And (Candles[Latter].Low < Candles[Former].Low) Then Result := dDown Else Result := dNeither End; { DescribeCandle } Var InitialDirection, CurrentDirection : TDirection; Begin { TUpCandles.VerifyCurrent } If PreviousEpoch <> CandleData.Epoch Then Begin PreviousEpoch := CandleData.Epoch; Candles := CandleData.GetHistory; InitialDirection := DescribeCandle(0); CurrentDirection := InitialDirection; FValue := 0; Repeat If (CurrentDirection = dEnd) Or (FValue > 100) Then Begin FValid := False; Break End; If (CurrentDirection = dNeither) Or (CurrentDirection <> InitialDirection) Then Begin FValid := True; If InitialDirection = dDown Then FValue := -FValue; Break End; Inc(FValue); CurrentDirection := DescribeCandle(FValue) Until False End End; { TUpCandles.VerifyCurrent } Function TUpCandles.IsValid : Boolean; Begin VerifyCurrent; Result := FValid End; Constructor TUpCandles.Create(Params : TParamList); Var Symbol : String; MinutesPerBar : Integer; Link : TDataNodeLink; Begin Assert(Length(Params)=2, 'Expected params: (Symbol, Minutes/Bar)'); Symbol := Params[0]; MinutesPerBar := Params[1]; Inherited Create; TStandardCandles.Find(Symbol, MinutesPerBar, NotifyListeners, CandleData, Link); AddAutoLink(Link) End; Function TUpCandles.GetInteger : Integer; Begin VerifyCurrent; Result := FValue End; Initialization TGenericDataNodeFactory.StoreFactory('UpCandles5', TGenericDataNodeFactory.CreateWithArgs(TUpCandles, StandardSymbolPlaceHolder, 5)); TGenericDataNodeFactory.StoreFactory('UpCandles10', TGenericDataNodeFactory.CreateWithArgs(TUpCandles, StandardSymbolPlaceHolder, 10)); TGenericDataNodeFactory.StoreFactory('UpCandles15', TGenericDataNodeFactory.CreateWithArgs(TUpCandles, StandardSymbolPlaceHolder, 15)); TGenericDataNodeFactory.StoreFactory('UpCandles30', TGenericDataNodeFactory.CreateWithArgs(TUpCandles, StandardSymbolPlaceHolder, 30)); TGenericDataNodeFactory.StoreFactory('UpCandles60', TGenericDataNodeFactory.CreateWithArgs(TUpCandles, StandardSymbolPlaceHolder, 60)); End.