Processor-Result

This commit is contained in:
Michael Schimmel
2025-07-11 12:00:36 +02:00
parent 487169afe0
commit 021ff61774
5 changed files with 52 additions and 32 deletions
+18 -16
View File
@@ -41,13 +41,12 @@ type
property Observers: IMycBroadcast<T> read GetObservers;
end;
TMycConverter<S, T> = class abstract(TInterfacedObject, IMycProcessor<S>, IMycConverter<S, T>)
TMycConverter<S, T> = class abstract(TMycProcessor<S>, IMycConverter<S, T>)
private
FObservers: TMycBroadcast<T>;
protected
procedure Broadcast(const Value: T);
function GetObservers: IMycBroadcast<T>;
procedure ProcessData(const Value: S); virtual; abstract;
public
constructor Create;
destructor Destroy; override;
@@ -59,7 +58,7 @@ type
private
FFunc: TConvertFunc;
protected
procedure ProcessData(const Value: S); override;
function ProcessData(const Value: S): Boolean; override;
public
constructor Create(const AFunc: TConvertFunc);
end;
@@ -79,7 +78,7 @@ type
TMycIndicator<S, T> = class abstract(TMycConverter<TArray<S>, TArray<T>>, IMycIndicator<S, T>)
protected
function GetLookback: Integer; virtual; abstract;
procedure ProcessData(const Value: TArray<S>); override; abstract;
function ProcessData(const Value: TArray<S>): Boolean; override; abstract;
public
property Lookback: Integer read GetLookback;
end;
@@ -92,7 +91,7 @@ type
FFunc: TConvertFunc;
protected
function GetLookback: Integer; override;
procedure ProcessData(const Value: TArray<S>); override;
function ProcessData(const Value: TArray<S>): Boolean; override;
public
constructor Create(ALookback: Integer; const AFunc: TConvertFunc);
end;
@@ -120,7 +119,7 @@ type
constructor Create(const ATimeframe: TTimeframe; const AStateText: TWriteable<String>);
// Process new data. This is called concurrently and must not have side effects out of the scope of this class!
procedure ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>); override;
function ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>): Boolean; override;
property CurrentBar: TDataPoint<TOhlcItem> read GetCurrentBar;
property StateText: TWriteable<String> read GetStateText;
@@ -140,7 +139,7 @@ type
// Calculates the Weighted Moving Average for the most recent data.
function CalculateWMA(const Series: TMycDataArray<Double>; const Period: Integer): Double;
protected
procedure ProcessData(const Values: TArray<Double>); override;
function ProcessData(const Values: TArray<Double>): Boolean; override;
function GetLookback: Integer; override;
public
constructor Create(const APeriod: Integer);
@@ -175,8 +174,7 @@ begin
FLinkedStrategies.Notify(
function(const Processor: IMycProcessor<T>): Boolean
begin
Processor.ProcessData(cValue);
Result := true;
Result := Processor.ProcessData(cValue);
end
);
finally
@@ -242,7 +240,7 @@ begin
Result := FTimeframe;
end;
procedure TTicksToTimeframe.ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>);
function TTicksToTimeframe.ProcessData(const Values: TArray<TDataPoint<TAskBidItem>>): Boolean;
var
point: TDataPoint<TAskBidItem>;
midPrice: Single;
@@ -251,6 +249,7 @@ var
currentBar: TOhlcItem;
producedBars: TList<TDataPoint<TOhlcItem>>;
begin
Result := true;
producedBars := TList<TDataPoint<TOhlcItem>>.Create;
try
// Process each incoming data point
@@ -343,7 +342,7 @@ begin
Result := FPeriod + FPeriodSqrt - 1;
end;
procedure THullMovingAverage.ProcessData(const Values: TArray<Double>);
function THullMovingAverage.ProcessData(const Values: TArray<Double>): Boolean;
var
i: Integer;
price: Double;
@@ -351,6 +350,8 @@ var
hma: Double;
resultArray: TArray<Double>;
begin
Result := true;
// Pre-allocate the result array since its size is known in advance.
SetLength(resultArray, Length(Values));
@@ -358,8 +359,8 @@ begin
begin
price := Values[i];
// Default HMA to 0.0 for the warm-up period.
hma := 0.0;
// Default HMA to NaN for the warm-up period.
hma := Double.NaN;
// Add new price to the source data array, respecting the lookback period.
FSourceData := FSourceData.Add(price, FPeriod);
@@ -402,8 +403,9 @@ begin
FFunc := AFunc;
end;
procedure TMycGenericConverter<S, T>.ProcessData(const Value: S);
function TMycGenericConverter<S, T>.ProcessData(const Value: S): Boolean;
begin
Result := true;
Broadcast(FFunc(Value));
end;
@@ -419,11 +421,11 @@ begin
Result := FLookback;
end;
procedure TMycGenericIndicator<S, T>.ProcessData(const Value: TArray<S>);
function TMycGenericIndicator<S, T>.ProcessData(const Value: TArray<S>): Boolean;
var
Arr: TArray<T>;
begin
inherited;
Result := true;
SetLength(Arr, Length(Value));
for var i := 0 to High(Arr) do
Arr[i] := FFunc(Value[i]);
+2 -1
View File
@@ -450,8 +450,9 @@ begin
Symbol,
terminated,
TMycGenericProcessor<TArray<TDataPoint<TAuraAskBidFileItem>>>.Create(
procedure(const Values: TArray<TDataPoint<TAuraAskBidFileItem>>)
function(const Values: TArray<TDataPoint<TAuraAskBidFileItem>>): Boolean
begin
Result := true;
Prices := Prices.Add(Values);
currLog.Value := Prices.TotalCount.ToString;
+14 -4
View File
@@ -78,7 +78,7 @@ type
FDataSeries: TMycDataArray<T>;
FChanged: Boolean;
FLock: TSpinLock;
procedure ProcessData(const Values: TArray<T>);
function ProcessData(const Values: TArray<T>): Boolean;
private
FData: TMycDataArray<T>;
protected
@@ -271,8 +271,9 @@ begin
Result := FData.Count;
end;
procedure TChartSeriesProcessor<T>.ProcessData(const Values: TArray<T>);
function TChartSeriesProcessor<T>.ProcessData(const Values: TArray<T>): Boolean;
begin
Result := true;
FLock.Enter;
try
FDataSeries := FDataSeries.Add(Values, 0, Length(Values), Owner.Lookback);
@@ -407,8 +408,17 @@ begin
if displayCount < 2 then
Exit;
points.MoveTo( TPointF.Create(AXForm(0), AYForm(Data[0])) );
for var i := 1 to displayCount - 1 do
// Skip warmup data
var n := 0;
while IsNaN(Data[n]) do
begin
inc( n );
if n >= displaycount-2 then
exit;
end;
points.MoveTo( TPointF.Create(AXForm(n), AYForm(Data[n])) );
for var i := n to displayCount - 1 do
points.LineTo( TPointF.Create(AXForm(i), AYForm(Data[i])) );
ACanvas.Stroke.Color := FLineColor;
+15 -10
View File
@@ -30,25 +30,30 @@ type
end;
IMycProcessor<T> = interface
procedure ProcessData(const Value: T);
function ProcessData(const Value: T): Boolean;
end;
TMycGenericProcessor<T> = class(TInterfacedObject, IMycProcessor<T>)
TMycProcessor<T> = class abstract(TInterfacedObject, IMycProcessor<T>)
protected
function ProcessData(const Value: T): Boolean; virtual; abstract;
end;
TMycGenericProcessor<T> = class(TMycProcessor<T>)
type
TProc = reference to procedure(const Value: T);
TProc = reference to function(const Value: T): Boolean;
private
FProc: TProc;
procedure ProcessData(const Value: T);
function ProcessData(const Value: T): Boolean; override;
public
constructor Create(const AProc: TProc);
end;
TMycContainedProcessor<T> = class(TContainedObject, IMycProcessor<T>)
type
TProc = procedure(const Value: T) of object;
TProc = function(const Value: T): Boolean of object;
private
FProc: TProc;
procedure ProcessData(const Value: T);
function ProcessData(const Value: T): Boolean;
public
constructor Create(const Controller: IInterface; const AProc: TProc);
end;
@@ -420,9 +425,9 @@ begin
FProc := AProc;
end;
procedure TMycGenericProcessor<T>.ProcessData(const Value: T);
function TMycGenericProcessor<T>.ProcessData(const Value: T): Boolean;
begin
FProc(Value);
Result := FProc(Value);
end;
constructor TMycContainedProcessor<T>.Create(const Controller: IInterface; const AProc: TProc);
@@ -431,9 +436,9 @@ begin
FProc := AProc;
end;
procedure TMycContainedProcessor<T>.ProcessData(const Value: T);
function TMycContainedProcessor<T>.ProcessData(const Value: T): Boolean;
begin
FProc(Value);
Result := FProc(Value);
end;
end.
+3 -1
View File
@@ -436,7 +436,9 @@ begin
DataFile.Chain(
function(const Data: TArray<TDataPoint<T>>): TState
begin
Processor.ProcessData(Data);
if not Processor.ProcessData(Data) then
exit( TState.Null );
Result := ProcessFile(nextFileInfo, nextFile, cTerminated, Processor);
end
);