Sample SMA strategy

This commit is contained in:
Michael Schimmel
2025-09-03 13:41:24 +02:00
parent 3e4ca283c9
commit 6b9dcee417
9 changed files with 505 additions and 179 deletions
+75 -53
View File
@@ -303,16 +303,8 @@ begin
memberName := Node.Member.Name;
case baseValue.Kind of
avkRecordSeries:
begin
var series := baseValue.AsRecordSeries;
Result := TAstValue.FromMemberSeries(series.CreateMemberSeries(memberName));
end;
avkRecord:
begin
var recordValue := baseValue.AsRecord;
Result := TAstValue.FromScalar(recordValue.Items[memberName]);
end;
avkRecordSeries: Result := TAstValue.FromMemberSeries(baseValue.AsRecordSeries.CreateMemberSeries(memberName));
avkRecord: Result := TAstValue.FromScalar(baseValue.AsRecord.Items[memberName]);
else
raise EArgumentException.Create('Member access operator `.` is not supported for this value type.');
end;
@@ -381,6 +373,8 @@ begin
end;
innerVisitor := Self.CreateVisitorForScope(callScope);
callScope.SetValue('Self', calleeValue);
callScope.SetValue('Result', TAstValue.Void);
Result := closure.Body.Accept(innerVisitor);
end
@@ -392,56 +386,78 @@ function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNo
var
leftValue, rightValue: TAstValue;
leftScalar, rightScalar: TScalar;
leftVal, rightVal: Int64;
boolResult: Boolean;
intResult: Int64;
begin
// Implemented binary operators for Int64 and Double.
leftValue := Node.Left.Accept(Self);
rightValue := Node.Right.Accept(Self);
if leftValue.Kind <> rightValue.Kind then
raise ENotSupportedException.Create('Binary operations are only supported for compatible types.');
if leftValue.Kind <> avkScalar then
begin
if (leftValue.Kind <> avkScalar) or (rightValue.Kind <> avkScalar) then
raise ENotSupportedException.Create('Binary operations are only supported for scalar types.');
end;
leftScalar := leftValue.AsScalar;
rightScalar := rightValue.AsScalar;
if (leftScalar.Kind <> skInt64) or (rightScalar.Kind <> skInt64) then
if (leftScalar.Kind <> rightScalar.Kind) then
begin
raise ENotSupportedException.Create('Binary operations currently only support Int64.');
end;
leftVal := leftScalar.Value.AsInt64;
rightVal := rightScalar.Value.AsInt64;
case Node.Operator of
boEqual: boolResult := (leftVal = rightVal);
boNotEqual: boolResult := (leftVal <> rightVal);
boLess: boolResult := (leftVal < rightVal);
boGreater: boolResult := (leftVal > rightVal);
boLessOrEqual: boolResult := (leftVal <= rightVal);
boGreaterOrEqual: boolResult := (leftVal >= rightVal);
else
case Node.Operator of
boAdd: intResult := leftVal + rightVal;
boSubtract: intResult := leftVal - rightVal;
boMultiply: intResult := leftVal * rightVal;
boDivide: intResult := leftVal div rightVal;
// Automatic type promotion from Int64 to Double.
if (leftScalar.Kind = skInt64) and (rightScalar.Kind = skDouble) then
begin
leftScalar := TScalar.FromDouble(leftScalar.Value.AsInt64);
end
else if (leftScalar.Kind = skDouble) and (rightScalar.Kind = skInt64) then
begin
rightScalar := TScalar.FromDouble(rightScalar.Value.AsInt64);
end
else
raise ENotSupportedException.Create('Operator not supported.');
begin
// If types are still different after promotion, they are incompatible.
raise ENotSupportedException.Create(
'Binary operations are only supported for compatible types. ' + leftScalar.ToString + ' ' + rightScalar.ToString);
end;
Result := TAstValue.FromScalar(TScalar.FromInt64(intResult));
exit;
end;
if boolResult then
Result := TAstValue.FromScalar(TScalar.FromBoolean(true))
case leftScalar.Kind of
skInt64:
begin
var leftVal := leftScalar.Value.AsInt64;
var rightVal := rightScalar.Value.AsInt64;
case Node.Operator of
boAdd: Result := TAstValue.FromScalar(TScalar.FromInt64(leftVal + rightVal));
boSubtract: Result := TAstValue.FromScalar(TScalar.FromInt64(leftVal - rightVal));
boMultiply: Result := TAstValue.FromScalar(TScalar.FromInt64(leftVal * rightVal));
boDivide: Result := TAstValue.FromScalar(TScalar.FromInt64(leftVal div rightVal));
boEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal = rightVal));
boNotEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal <> rightVal));
boLess: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal < rightVal));
boGreater: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal > rightVal));
boLessOrEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal <= rightVal));
boGreaterOrEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal >= rightVal));
else
raise ENotSupportedException.Create('Operator not supported for Int64.');
end;
end;
skDouble:
begin
var leftVal := leftScalar.Value.AsDouble;
var rightVal := rightScalar.Value.AsDouble;
case Node.Operator of
boAdd: Result := TAstValue.FromScalar(TScalar.FromDouble(leftVal + rightVal));
boSubtract: Result := TAstValue.FromScalar(TScalar.FromDouble(leftVal - rightVal));
boMultiply: Result := TAstValue.FromScalar(TScalar.FromDouble(leftVal * rightVal));
boDivide: Result := TAstValue.FromScalar(TScalar.FromDouble(leftVal / rightVal));
boEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal = rightVal));
boNotEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal <> rightVal));
boLess: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal < rightVal));
boGreater: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal > rightVal));
boLessOrEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal <= rightVal));
boGreaterOrEqual: Result := TAstValue.FromScalar(TScalar.FromBoolean(leftVal >= rightVal));
else
raise ENotSupportedException.Create('Operator not supported for Double.');
end;
end;
else
Result := TAstValue.FromScalar(TScalar.FromBoolean(false));
raise ENotSupportedException.Create('Binary operations are not supported for this scalar type.');
end;
end;
function TEvaluatorVisitor.VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue;
@@ -449,21 +465,27 @@ var
rightValue: TAstValue;
rightScalar: TScalar;
begin
// Implemented unary operators for Int64, Double, and Boolean.
rightValue := Node.Right.Accept(Self);
if rightValue.Kind <> avkScalar then
raise ENotSupportedException.Create('Unary operations are only supported for scalar types.');
rightScalar := rightValue.AsScalar;
case Node.Operator of
uoNegate:
begin
if (rightScalar.Kind = skInt64) then
Result := TAstValue.FromScalar(TScalar.FromInt64(-rightScalar.Value.AsInt64))
if (rightValue.Kind <> avkScalar) then
raise ENotSupportedException.Create('Unary "-" is only supported for scalar types.');
rightScalar := rightValue.AsScalar;
case rightScalar.Kind of
skInt64: Result := TAstValue.FromScalar(TScalar.FromInt64(-rightScalar.Value.AsInt64));
skDouble: Result := TAstValue.FromScalar(TScalar.FromDouble(-rightScalar.Value.AsDouble));
else
raise ENotSupportedException.Create('Unary "-" not supported for this scalar type.');
raise ENotSupportedException.Create('Unary "-" is not supported for this scalar type.');
end;
end;
uoNot:
begin
// "not" operates on the truthiness of the value.
Result := TAstValue.FromScalar(TScalar.FromBoolean(not IsTruthy(rightValue)));
end;
uoNot: raise ENotImplemented.Create('Unary "not" operator is not yet implemented');
else
raise ENotSupportedException.Create('Unary operator not supported');
end;