Refactoring TradingBotBase.cs + clean architecture (#38)
* Refactoring TradingBotBase.cs + clean architecture * Fix basic tests * Fix tests * Fix workers * Fix open positions * Fix closing position stucking the grain * Fix comments * Refactor candle handling to use IReadOnlyList for chronological order preservation across various components
This commit is contained in:
@@ -372,6 +372,8 @@ namespace Managing.Infrastructure.Databases.Migrations
|
||||
b.HasIndex("Identifier")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MasterBotUserId");
|
||||
|
||||
b.HasIndex("Status");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
@@ -929,6 +931,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("TradingType")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<decimal>("UiFees")
|
||||
.HasColumnType("decimal(18,8)");
|
||||
|
||||
@@ -1571,12 +1576,19 @@ namespace Managing.Infrastructure.Databases.Migrations
|
||||
|
||||
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.BotEntity", b =>
|
||||
{
|
||||
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "MasterBotUser")
|
||||
.WithMany()
|
||||
.HasForeignKey("MasterBotUserId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.SetNull)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("MasterBotUser");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
|
||||
@@ -57,4 +57,9 @@ public class PositionEntity
|
||||
[ForeignKey("TakeProfit2TradeId")] public virtual TradeEntity? TakeProfit2Trade { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,8)")] public decimal NetPnL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The trading type for this position (BacktestFutures or Futures)
|
||||
/// </summary>
|
||||
public TradingType TradingType { get; set; }
|
||||
}
|
||||
@@ -331,6 +331,13 @@ public static class PostgreSqlMappers
|
||||
{
|
||||
if (backtest == null) return null;
|
||||
|
||||
// Configure JSON serializer to handle circular references
|
||||
var jsonSettings = new JsonSerializerSettings
|
||||
{
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
PreserveReferencesHandling = PreserveReferencesHandling.None
|
||||
};
|
||||
|
||||
return new BacktestEntity
|
||||
{
|
||||
Identifier = backtest.Id,
|
||||
@@ -339,20 +346,20 @@ public static class PostgreSqlMappers
|
||||
WinRate = backtest.WinRate,
|
||||
GrowthPercentage = backtest.GrowthPercentage,
|
||||
HodlPercentage = backtest.HodlPercentage,
|
||||
ConfigJson = JsonConvert.SerializeObject(backtest.Config),
|
||||
ConfigJson = JsonConvert.SerializeObject(backtest.Config, jsonSettings),
|
||||
Name = backtest.Config?.Name ?? string.Empty,
|
||||
Ticker = backtest.Config?.Ticker.ToString() ?? string.Empty,
|
||||
Timeframe = (int)backtest.Config.Timeframe,
|
||||
IndicatorsCsv = string.Join(',', backtest.Config.Scenario.Indicators.Select(i => i.Type.ToString())),
|
||||
IndicatorsCount = backtest.Config.Scenario.Indicators.Count,
|
||||
PositionsJson = JsonConvert.SerializeObject(backtest.Positions.Values.ToList()),
|
||||
SignalsJson = JsonConvert.SerializeObject(backtest.Signals.Values.ToList()),
|
||||
PositionsJson = JsonConvert.SerializeObject(backtest.Positions.Values.ToList(), jsonSettings),
|
||||
SignalsJson = JsonConvert.SerializeObject(backtest.Signals.Values.ToList(), jsonSettings),
|
||||
StartDate = backtest.StartDate,
|
||||
EndDate = backtest.EndDate,
|
||||
Duration = backtest.EndDate - backtest.StartDate,
|
||||
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement),
|
||||
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement, jsonSettings),
|
||||
UserId = backtest.User?.Id ?? 0,
|
||||
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics) : null,
|
||||
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics, jsonSettings) : null,
|
||||
SharpeRatio = backtest.Statistics?.SharpeRatio ?? 0m,
|
||||
MaxDrawdown = backtest.Statistics?.MaxDrawdown ?? 0m,
|
||||
MaxDrawdownRecoveryTime = backtest.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero,
|
||||
@@ -615,7 +622,8 @@ public static class PostgreSqlMappers
|
||||
{
|
||||
Status = entity.Status,
|
||||
SignalIdentifier = entity.SignalIdentifier,
|
||||
InitiatorIdentifier = entity.InitiatorIdentifier
|
||||
InitiatorIdentifier = entity.InitiatorIdentifier,
|
||||
TradingType = entity.TradingType
|
||||
};
|
||||
|
||||
// Set ProfitAndLoss with proper type
|
||||
@@ -657,6 +665,7 @@ public static class PostgreSqlMappers
|
||||
SignalIdentifier = position.SignalIdentifier,
|
||||
UserId = position.User?.Id ?? 0,
|
||||
InitiatorIdentifier = position.InitiatorIdentifier,
|
||||
TradingType = position.TradingType,
|
||||
MoneyManagementJson = position.MoneyManagement != null
|
||||
? JsonConvert.SerializeObject(position.MoneyManagement)
|
||||
: null,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Managing.Infrastructure.Databases.src.Managing.Infrastructure.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddTradingTypeToPositions : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TradingType",
|
||||
table: "Positions",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Bots_MasterBotUserId",
|
||||
table: "Bots",
|
||||
column: "MasterBotUserId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Bots_Users_MasterBotUserId",
|
||||
table: "Bots",
|
||||
column: "MasterBotUserId",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Bots_Users_MasterBotUserId",
|
||||
table: "Bots");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Bots_MasterBotUserId",
|
||||
table: "Bots");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TradingType",
|
||||
table: "Positions");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user