Ast Refactoring

This commit is contained in:
Michael Schimmel
2025-09-03 22:55:43 +02:00
parent 48bc763e41
commit a5fd079875
5 changed files with 442 additions and 460 deletions
+45 -33
View File
@@ -21,7 +21,6 @@ uses
FMX.ScrollBox,
FMX.Memo,
FMX.Controls.Presentation,
DraggablePanel,
Myc.Ast.Visualizer,
Myc.Data.Scalar,
Myc.Ast.Nodes,
@@ -691,51 +690,55 @@ begin
recordDef := TRttiAstHelper.JsonToRecordDefinition(TRttiAstHelper.RecordDefinitionToJson(TypeInfo(TOHLCV)));
series := TScalarRecordSeries.Create(recordDef);
// 2. Create the setup AST with O(1) SMA implementation
// 2. Create the setup AST with the optimized O(1) SMA implementation
setupAst :=
TAst.Block(
[
// This factory is now much simpler. It only manages sum and a counter.
TAst.VarDecl(
TAst.Identifier('CreateSMA_O1'),
TAst.Identifier('CreateSMA'),
TAst.LambdaExpr(
[TAst.Identifier('len')],
TAst.Block(
[
TAst.VarDecl(TAst.Identifier('sum'), TAst.Constant(TScalar.FromDouble(0.0))),
TAst.VarDecl(TAst.Identifier('values'), TAst.CreateSeries('double')),
TAst.VarDecl(TAst.Identifier('count'), TAst.Constant(TScalar.FromInt64(0))),
// The returned closure now takes the full series and the new value.
TAst.LambdaExpr(
[TAst.Identifier('val')],
[TAst.Identifier('series'), TAst.Identifier('val')],
TAst.Block(
[
TAst.Assign(
TAst.Identifier('sum'),
TAst.BinaryExpr(TAst.Identifier('sum'), boAdd, TAst.Identifier('val'))
),
TAst.Assign(
TAst.Identifier('count'),
TAst.BinaryExpr(TAst.Identifier('count'), boAdd, TAst.Constant(TScalar.FromInt64(1)))
),
// If the indicator is "full", subtract the value that just fell out of the window (at index 'len').
TAst.IfExpr(
TAst.BinaryExpr(
TAst.SeriesLength(TAst.Identifier('values')),
boGreaterOrEqual,
TAst.Identifier('len')
),
TAst.BinaryExpr(TAst.Identifier('count'), boGreater, TAst.Identifier('len')),
TAst.Assign(
TAst.Identifier('sum'),
TAst.BinaryExpr(
TAst.Identifier('sum'),
boSubtract,
TAst.Indexer(
TAst.Identifier('values'),
TAst.BinaryExpr(
TAst.Identifier('len'),
boSubtract,
TAst.Constant(TScalar.FromInt64(1))
)
)
TAst.Indexer(TAst.Identifier('series'), TAst.Identifier('len'))
)
),
nil
),
TAst.Assign(
// Calculate and return the average. Divisor is capped at 'len'.
TAst.BinaryExpr(
TAst.Identifier('sum'),
TAst.BinaryExpr(TAst.Identifier('sum'), boAdd, TAst.Identifier('val'))
),
TAst.AddSeriesItem(TAst.Identifier('values'), TAst.Identifier('val'), TAst.Identifier('len')),
TAst.BinaryExpr(TAst.Identifier('sum'), boDivide, TAst.SeriesLength(TAst.Identifier('values')))
boDivide,
TAst.TernaryExpr(
TAst.BinaryExpr(TAst.Identifier('count'), boLess, TAst.Identifier('len')),
TAst.Identifier('count'),
TAst.Identifier('len')
)
)
]
)
)
@@ -743,34 +746,43 @@ begin
)
)
),
// Instantiation remains the same.
TAst.VarDecl(
TAst.Identifier('smaFast'),
TAst.FunctionCall(TAst.Identifier('CreateSMA_O1'), [TAst.Constant(TScalar.FromInt64(smaFastLength))])
TAst.FunctionCall(TAst.Identifier('CreateSMA'), [TAst.Constant(TScalar.FromInt64(smaFastLength))])
),
TAst.VarDecl(
TAst.Identifier('smaSlow'),
TAst.FunctionCall(TAst.Identifier('CreateSMA_O1'), [TAst.Constant(TScalar.FromInt64(smaSlowLength))])
TAst.FunctionCall(TAst.Identifier('CreateSMA'), [TAst.Constant(TScalar.FromInt64(smaSlowLength))])
),
// The main strategy now passes the full close series to the indicators.
TAst.VarDecl(
TAst.Identifier('maCrossStrategy'),
TAst.LambdaExpr(
[TAst.Identifier('ohlcv')],
TAst.Block(
[
TAst.VarDecl(
TAst.Identifier('closeSeries'),
TAst.MemberAccess(TAst.Identifier('ohlcv'), TAst.Identifier('Close'))
),
TAst.VarDecl(
TAst.Identifier('currentClose'),
TAst.MemberAccess(
TAst.Indexer(TAst.Identifier('ohlcv'), TAst.Constant(TScalar.FromInt64(0))),
TAst.Identifier('Close')
)
TAst.Indexer(TAst.Identifier('closeSeries'), TAst.Constant(TScalar.FromInt64(0)))
),
TAst.VarDecl(
TAst.Identifier('valSmaFast'),
TAst.FunctionCall(TAst.Identifier('smaFast'), [TAst.Identifier('currentClose')])
TAst.FunctionCall(
TAst.Identifier('smaFast'),
[TAst.Identifier('closeSeries'), TAst.Identifier('currentClose')]
)
),
TAst.VarDecl(
TAst.Identifier('valSmaSlow'),
TAst.FunctionCall(TAst.Identifier('smaSlow'), [TAst.Identifier('currentClose')])
TAst.FunctionCall(
TAst.Identifier('smaSlow'),
[TAst.Identifier('closeSeries'), TAst.Identifier('currentClose')]
)
),
TAst.TernaryExpr(
TAst.BinaryExpr(TAst.Identifier('valSmaFast'), boGreater, TAst.Identifier('valSmaSlow')),
@@ -827,8 +839,8 @@ begin
FGScope.SetValue('current_series', TAstValue.FromRecordSeries(series));
resultValue := callAst.Accept(visitor);
// Memo1.Lines.Add(Format('Tick %d/%d: Close = %.2f, Signal = %s', [i, numRecs, ohlcvRec.Close, resultValue.ToString]));
// Application.ProcessMessages;
Memo1.Lines.Add(Format('Tick %d/%d: Close = %.2f, Signal = %s', [i, numRecs, ohlcvRec.Close, resultValue.ToString]));
Application.ProcessMessages;
end;
end;