191 lines
5.7 KiB
ObjectPascal
191 lines
5.7 KiB
ObjectPascal
unit StrategyTest;
|
|
|
|
interface
|
|
|
|
uses
|
|
Myc.Signals,
|
|
Myc.Trade.Types,
|
|
Myc.Trade.DataPoint,
|
|
Myc.Trade.DataArray,
|
|
Myc.DataRecord,
|
|
Myc.Trade.Indicators;
|
|
|
|
function CreateStrategy1(Timeframe: TTimeframe): TConverter<TDataPoint<TOhlcItem>, Double>;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Math;
|
|
|
|
function CreateStrategy1(Timeframe: TTimeframe): TConverter<TDataPoint<TOhlcItem>, Double>;
|
|
type
|
|
TSignal = record
|
|
Sig: Double;
|
|
SL: Double;
|
|
Entry: Double;
|
|
pnl: Double;
|
|
end;
|
|
begin
|
|
var ticker := TConverter.CreateIdentity<TDataPoint<TOhlcItem>>;
|
|
|
|
var OhlcPoint := ticker.Chain<TDataPoint<TOhlcItem>>(TConverter.CreateOhlcAggregation(Timeframe));
|
|
|
|
var Ohlc := OhlcPoint.Field<TOhlcItem>('Data');
|
|
|
|
var Closes := Ohlc.Field<Double>('Close');
|
|
|
|
var Hull := Closes.Chain<Double>(TIndicators.CreateHMA(250)).MakeParallel;
|
|
var Sma := Closes.Chain<Double>(TIndicators.CreateSMA(200)).MakeParallel;
|
|
|
|
var Lowest: Double := Double.MaxValue;
|
|
var Highest: Double := Double.MinValue;
|
|
|
|
var ATR := Ohlc.Chain<Double>(TIndicators.CreateATR(50)).MakeParallel;
|
|
|
|
// next stage
|
|
|
|
var ATREndPoint := TConverter.CreateEndpoint<Double>(ATR.Sender, 5);
|
|
var ATRSeries: TSeries<Double>;
|
|
|
|
var HullEndPoint := TConverter.CreateEndpoint<Double>(Hull.Sender, 5);
|
|
var HullSeries: TSeries<Double>;
|
|
|
|
var SmaEndPoint := TConverter.CreateEndpoint<Double>(Sma.Sender, 5);
|
|
var SmaSeries: TSeries<Double>;
|
|
|
|
var curr: TSignal;
|
|
curr.SL := Double.NaN;
|
|
curr.Entry := Double.NaN;
|
|
|
|
var lastHull, lastSma: Double;
|
|
|
|
var conv :=
|
|
TConverter.Join<Double>(
|
|
[Ohlc.Field<Double>('Low').Sender, Ohlc.Field<Double>('High').Sender, Closes.Sender, ATR.Sender, Hull.Sender, Sma.Sender]
|
|
);
|
|
|
|
var Signal :=
|
|
TConverter<TArray<Double>, TSignal>.CreateGeneric(
|
|
function(const Values: TArray<Double>): TSignal
|
|
begin
|
|
var low := Values[0];
|
|
var high := Values[1];
|
|
var close := Values[2];
|
|
var atr := Values[3];
|
|
var hull := Values[4];
|
|
var sma := Values[5];
|
|
|
|
if low < Lowest then
|
|
Lowest := low;
|
|
if high > Highest then
|
|
Highest := high;
|
|
|
|
Result := curr;
|
|
Result.Sig := 0;
|
|
var pnl: double := NaN;
|
|
|
|
if (hull < sma) and (lastHull >= lastSma) then
|
|
begin
|
|
if curr.Sig > 0 then
|
|
pnl := close - curr.Entry;
|
|
|
|
curr.Sig := -1;
|
|
curr.SL := Highest;
|
|
curr.Entry := close;
|
|
Result := curr;
|
|
end
|
|
else if (hull > sma) and (lastHull <= lastSma) then
|
|
begin
|
|
if curr.Sig < 0 then
|
|
pnl := curr.Entry - close;
|
|
|
|
curr.Sig := 1;
|
|
curr.SL := Lowest;
|
|
curr.Entry := close;
|
|
Result := curr;
|
|
end;
|
|
|
|
atr := 15 * atr;
|
|
if curr.Sig > 0 then
|
|
begin
|
|
if close > curr.SL then
|
|
begin
|
|
if curr.SL < close - atr then
|
|
curr.SL := close - atr;
|
|
Result.SL := curr.SL;
|
|
end;
|
|
|
|
if low <= curr.SL then
|
|
begin
|
|
pnl := curr.SL - curr.Entry;
|
|
curr.Sig := 0;
|
|
Result.Sig := 0;
|
|
curr.SL := NaN;
|
|
end;
|
|
end
|
|
else if curr.Sig < 0 then
|
|
begin
|
|
if close < curr.SL then
|
|
begin
|
|
if curr.SL > close + atr then
|
|
curr.SL := close + atr;
|
|
Result.SL := curr.SL;
|
|
end;
|
|
|
|
if high >= curr.SL then
|
|
begin
|
|
pnl := curr.Entry - curr.SL;
|
|
curr.Sig := 0;
|
|
Result.Sig := 0;
|
|
curr.SL := NaN;
|
|
end;
|
|
end;
|
|
|
|
if Result.Sig <> 0 then
|
|
begin
|
|
Lowest := Double.MaxValue;
|
|
Highest := Double.MinValue;
|
|
Result.SL := Double.NaN;
|
|
Result.Entry := Double.NaN;
|
|
end;
|
|
|
|
Result.pnl := pnl;
|
|
|
|
lastHull := hull;
|
|
lastSma := sma;
|
|
end
|
|
);
|
|
|
|
conv.Link(Signal);
|
|
|
|
var pnl := Signal.Field<Double>('pnl');
|
|
|
|
var FEquity: Double := 10000;
|
|
var FInit: Boolean := false;
|
|
|
|
var equity :=
|
|
TConverter<Double, Double>.CreateAggregation(
|
|
function(const Value: Double; const Broadcast: TConverter<Double, Double>.TBroadcastProc): TState
|
|
begin
|
|
if not FInit then
|
|
begin
|
|
FInit := true;
|
|
Broadcast(FEquity);
|
|
end;
|
|
|
|
if not IsNan(Value) then
|
|
begin
|
|
FEquity := FEquity + Value;
|
|
Result := Broadcast(FEquity);
|
|
end;
|
|
end
|
|
);
|
|
|
|
pnl.Sender.Link(equity);
|
|
|
|
Result := TConverter<TDataPoint<TOhlcItem>, Double>.Construct(ticker, equity.Sender);
|
|
end;
|
|
|
|
end.
|