unit TestMethodCallFromRecordParams; interface uses System.SysUtils, System.Classes, System.Rtti, Myc.Data.Records, Myc.Data.Pipeline, Myc.Trade.Indicators; type TMyWorker = class public type TParams = record Log: Int64; text: String; end; TArgs = record xyz: Double; end; TResult = record val: Int64; desc: String; end; [IndicatorFactory] class function CreateFactory: TIndicatorFactoryProc; static; end; // SMA indicator for demonstration purposes TSmaIndicator = class public type TParams = record Period: Integer; end; TArgs = record Value: Double; end; TResult = record Sma: Double; end; [IndicatorFactory] class function CreateFactory: TIndicatorFactoryProc; static; end; procedure Test1(const Log: TStrings); implementation uses System.Math; class function TMyWorker.CreateFactory: TIndicatorFactoryProc; begin Result := function(const Params: TParams): TConvertFunc begin var Log := TStrings(Params.Log); var text := Params.text; Result := function(const Args: TArgs): TResult begin // Use Format to avoid locale issues with float conversion Log.Add(Format('Val=%f (...%s)', [Args.xyz, text])); Result.desc := 'done'; end; end; end; procedure Test1(const Log: TStrings); begin var fact := TGenericIndicatorFactory.CreateFromTemplate; var params: TMyWorker.TParams; params.Log := Int64(Log); params.text := 'The quick brown fox jumps...'; var indi := fact.CreateIndicator(params); var args: TMyWorker.TArgs; args.xyz := 3.14159; var res := indi(args); Log.Add('Final result description: ' + res.desc); end; { TSmaIndicator } class function TSmaIndicator.CreateFactory: TIndicatorFactoryProc; begin Result := function(const Params: TParams): TConvertFunc var // State for the indicator closure period: Integer; buffer: TArray; sum: Double; count: Integer; idx: Integer; begin period := Params.Period; if period <= 0 then raise Exception.Create('Period must be positive'); SetLength(buffer, period); sum := 0.0; count := 0; idx := 0; Result := function(const Args: TArgs): TResult begin // If the buffer is full, subtract the oldest value that is about to be overwritten. if count >= period then sum := sum - buffer[idx]; // Add the new value to the buffer and the sum. buffer[idx] := Args.Value; sum := sum + Args.Value; // Advance the index for the circular buffer. idx := (idx + 1) mod period; // Increment the fill count until the buffer is full for the first time. if count < period then inc(count); // Calculate the SMA. The result is the average of the values currently in the buffer. if count > 0 then Result.Sma := sum / count else Result.Sma := 0.0; end; end; end; end.