Clean tradingbot and spot and future
This commit is contained in:
@@ -36,12 +36,12 @@ public class BacktestFuturesBot : TradingBotBase, ITradingBot
|
|||||||
// Backtest mode: Skip account loading and broker initialization
|
// Backtest mode: Skip account loading and broker initialization
|
||||||
// Just log basic startup info
|
// Just log basic startup info
|
||||||
await LogInformation($"🔬 Backtest Bot Started\n" +
|
await LogInformation($"🔬 Backtest Bot Started\n" +
|
||||||
$"📊 Testing Setup:\n" +
|
$"📊 Testing Setup:\n" +
|
||||||
$"🎯 Ticker: `{Config.Ticker}`\n" +
|
$"🎯 Ticker: `{Config.Ticker}`\n" +
|
||||||
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
|
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
|
||||||
$"🎮 Scenario: `{Config.Scenario?.Name ?? "Unknown"}`\n" +
|
$"🎮 Scenario: `{Config.Scenario?.Name ?? "Unknown"}`\n" +
|
||||||
$"💰 Initial Balance: `${Config.BotTradingBalance:F2}`\n" +
|
$"💰 Initial Balance: `${Config.BotTradingBalance:F2}`\n" +
|
||||||
$"✅ Ready to run backtest simulation");
|
$"✅ Ready to run backtest simulation");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Run()
|
public override async Task Run()
|
||||||
@@ -68,12 +68,6 @@ public class BacktestFuturesBot : TradingBotBase, ITradingBot
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<List<Position>> GetBrokerPositionsForUpdate(Account account)
|
|
||||||
{
|
|
||||||
// In backtest mode, return empty list (no broker positions to check)
|
|
||||||
return new List<Position>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
||||||
{
|
{
|
||||||
// In backtest mode, skip broker synchronization
|
// In backtest mode, skip broker synchronization
|
||||||
@@ -289,7 +283,8 @@ public class BacktestFuturesBot : TradingBotBase, ITradingBot
|
|||||||
_scopeFactory, async (exchangeService, accountService, tradingService) =>
|
_scopeFactory, async (exchangeService, accountService, tradingService) =>
|
||||||
{
|
{
|
||||||
closedPosition =
|
closedPosition =
|
||||||
await new CloseBacktestFuturesPositionCommandHandler(exchangeService, accountService, tradingService,
|
await new CloseBacktestFuturesPositionCommandHandler(exchangeService, accountService,
|
||||||
|
tradingService,
|
||||||
_scopeFactory)
|
_scopeFactory)
|
||||||
.Handle(command);
|
.Handle(command);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ public class BacktestSpotBot : TradingBotBase, ITradingBot
|
|||||||
// Backtest mode: Skip account loading and broker initialization
|
// Backtest mode: Skip account loading and broker initialization
|
||||||
// Just log basic startup info
|
// Just log basic startup info
|
||||||
await LogInformation($"🔬 Backtest Spot Bot Started\n" +
|
await LogInformation($"🔬 Backtest Spot Bot Started\n" +
|
||||||
$"📊 Testing Setup:\n" +
|
$"📊 Testing Setup:\n" +
|
||||||
$"🎯 Ticker: `{Config.Ticker}`\n" +
|
$"🎯 Ticker: `{Config.Ticker}`\n" +
|
||||||
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
|
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
|
||||||
$"🎮 Scenario: `{Config.Scenario?.Name ?? "Unknown"}`\n" +
|
$"🎮 Scenario: `{Config.Scenario?.Name ?? "Unknown"}`\n" +
|
||||||
$"💰 Initial Balance: `${Config.BotTradingBalance:F2}`\n" +
|
$"💰 Initial Balance: `${Config.BotTradingBalance:F2}`\n" +
|
||||||
$"✅ Ready to run spot backtest simulation");
|
$"✅ Ready to run spot backtest simulation");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Run()
|
public override async Task Run()
|
||||||
@@ -67,12 +67,6 @@ public class BacktestSpotBot : TradingBotBase, ITradingBot
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<List<Position>> GetBrokerPositionsForUpdate(Account account)
|
|
||||||
{
|
|
||||||
// In backtest mode, return empty list (no broker positions to check)
|
|
||||||
return new List<Position>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
||||||
{
|
{
|
||||||
// In backtest mode, skip broker synchronization
|
// In backtest mode, skip broker synchronization
|
||||||
@@ -247,7 +241,8 @@ public class BacktestSpotBot : TradingBotBase, ITradingBot
|
|||||||
// Only LONG signals should reach here (SHORT signals are filtered out earlier)
|
// Only LONG signals should reach here (SHORT signals are filtered out earlier)
|
||||||
if (signal.Direction != TradeDirection.Long)
|
if (signal.Direction != TradeDirection.Long)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Only LONG signals can open positions in spot trading. Received: {signal.Direction}");
|
throw new InvalidOperationException(
|
||||||
|
$"Only LONG signals can open positions in spot trading. Received: {signal.Direction}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Account == null || Account.User == null)
|
if (Account == null || Account.User == null)
|
||||||
@@ -330,5 +325,4 @@ public class BacktestSpotBot : TradingBotBase, ITradingBot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,14 +75,6 @@ public class FuturesBot : TradingBotBase, ITradingBot
|
|||||||
async tradingService => { return await tradingService.GetPositionByIdentifierAsync(position.Identifier); });
|
async tradingService => { return await tradingService.GetPositionByIdentifierAsync(position.Identifier); });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<List<Position>> GetBrokerPositionsForUpdate(Account account)
|
|
||||||
{
|
|
||||||
// For live trading, get real broker positions
|
|
||||||
return await ServiceScopeHelpers.WithScopedService<IExchangeService, List<Position>>(
|
|
||||||
_scopeFactory,
|
|
||||||
async exchangeService => { return [.. await exchangeService.GetBrokerPositions(Account)]; });
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
||||||
{
|
{
|
||||||
// Live trading broker position synchronization logic is handled in the base UpdatePosition method
|
// Live trading broker position synchronization logic is handled in the base UpdatePosition method
|
||||||
@@ -210,11 +202,16 @@ public class FuturesBot : TradingBotBase, ITradingBot
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override async Task SynchronizeWithBrokerPositions(Position internalPosition, Position positionForSignal,
|
protected override async Task SynchronizeWithBrokerPositions(
|
||||||
List<Position> brokerPositions)
|
Position internalPosition,
|
||||||
|
Position positionForSignal)
|
||||||
{
|
{
|
||||||
|
var liveBrokerPositions = await ServiceScopeHelpers.WithScopedService<IExchangeService, List<Position>>(
|
||||||
|
_scopeFactory,
|
||||||
|
async exchangeService => [.. await exchangeService.GetBrokerPositions(Account)]);
|
||||||
|
|
||||||
// Improved broker position matching with more robust logic
|
// Improved broker position matching with more robust logic
|
||||||
var brokerPosition = brokerPositions
|
var brokerPosition = liveBrokerPositions
|
||||||
.Where(p => p.Ticker == Config.Ticker)
|
.Where(p => p.Ticker == Config.Ticker)
|
||||||
.OrderByDescending(p => p.Open?.Date ?? DateTime.MinValue)
|
.OrderByDescending(p => p.Open?.Date ?? DateTime.MinValue)
|
||||||
.FirstOrDefault(p => p.OriginDirection == positionForSignal.OriginDirection);
|
.FirstOrDefault(p => p.OriginDirection == positionForSignal.OriginDirection);
|
||||||
@@ -284,7 +281,7 @@ public class FuturesBot : TradingBotBase, ITradingBot
|
|||||||
Logger.LogWarning(
|
Logger.LogWarning(
|
||||||
$"⚠️ Position Sync Issue Detected\n" +
|
$"⚠️ Position Sync Issue Detected\n" +
|
||||||
$"Internal position {internalPosition.Identifier} shows Filled\n" +
|
$"Internal position {internalPosition.Identifier} shows Filled\n" +
|
||||||
$"But not found in broker positions list (Count: {brokerPositions.Count})\n" +
|
$"But not found in broker positions list (Count: {liveBrokerPositions.Count})\n" +
|
||||||
$"Checking position history before marking as closed...");
|
$"Checking position history before marking as closed...");
|
||||||
|
|
||||||
// Verify in exchange history before assuming it's closed
|
// Verify in exchange history before assuming it's closed
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#nullable enable
|
||||||
using Managing.Application.Abstractions.Grains;
|
using Managing.Application.Abstractions.Grains;
|
||||||
using Managing.Application.Abstractions.Services;
|
using Managing.Application.Abstractions.Services;
|
||||||
using Managing.Application.Trading.Commands;
|
using Managing.Application.Trading.Commands;
|
||||||
@@ -68,15 +69,7 @@ public class SpotBot : TradingBotBase
|
|||||||
// For live trading, get position from database via trading service
|
// For live trading, get position from database via trading service
|
||||||
return await ServiceScopeHelpers.WithScopedService<ITradingService, Position>(
|
return await ServiceScopeHelpers.WithScopedService<ITradingService, Position>(
|
||||||
_scopeFactory,
|
_scopeFactory,
|
||||||
async tradingService => { return await tradingService.GetPositionByIdentifierAsync(position.Identifier); });
|
async tradingService => await tradingService.GetPositionByIdentifierAsync(position.Identifier));
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task<List<Position>> GetBrokerPositionsForUpdate(Account account)
|
|
||||||
{
|
|
||||||
// For live spot trading, we don't have broker positions like futures
|
|
||||||
// Positions are verified via token balances in UpdatePositionWithBrokerData and SynchronizeWithBrokerPositions
|
|
||||||
// Return empty list - actual verification happens in those methods
|
|
||||||
return new List<Position>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
protected override async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
||||||
@@ -88,7 +81,7 @@ public class SpotBot : TradingBotBase
|
|||||||
_scopeFactory,
|
_scopeFactory,
|
||||||
async exchangeService => await exchangeService.GetBalance(Account, Config.Ticker));
|
async exchangeService => await exchangeService.GetBalance(Account, Config.Ticker));
|
||||||
|
|
||||||
if (tokenBalance == null || tokenBalance.Amount <= 0)
|
if (tokenBalance is not { Amount: > 0 })
|
||||||
{
|
{
|
||||||
// No token balance found - position might be closed
|
// No token balance found - position might be closed
|
||||||
return;
|
return;
|
||||||
@@ -225,8 +218,7 @@ public class SpotBot : TradingBotBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override async Task SynchronizeWithBrokerPositions(Position internalPosition, Position positionForSignal,
|
protected override async Task SynchronizeWithBrokerPositions(Position internalPosition, Position positionForSignal)
|
||||||
List<Position> brokerPositions)
|
|
||||||
{
|
{
|
||||||
// For spot trading, fetch token balance directly and verify/match with internal position
|
// For spot trading, fetch token balance directly and verify/match with internal position
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -462,10 +462,9 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
}
|
}
|
||||||
|
|
||||||
Position internalPosition = await GetInternalPositionForUpdate(positionForSignal);
|
Position internalPosition = await GetInternalPositionForUpdate(positionForSignal);
|
||||||
var brokerPositions = await GetBrokerPositionsForUpdate(Account);
|
|
||||||
|
|
||||||
// Handle broker position synchronization (futures-specific logic)
|
// Handle broker position synchronization (futures-specific logic)
|
||||||
await SynchronizeWithBrokerPositions(internalPosition, positionForSignal, brokerPositions);
|
await SynchronizeWithBrokerPositions(internalPosition, positionForSignal);
|
||||||
|
|
||||||
// Handle order management and position status (futures-specific logic)
|
// Handle order management and position status (futures-specific logic)
|
||||||
await HandleOrderManagementAndPositionStatus(signal, internalPosition, positionForSignal);
|
await HandleOrderManagementAndPositionStatus(signal, internalPosition, positionForSignal);
|
||||||
@@ -650,8 +649,7 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Virtual methods for trading mode-specific behavior
|
// Virtual methods for trading mode-specific behavior
|
||||||
protected virtual async Task SynchronizeWithBrokerPositions(Position internalPosition, Position positionForSignal,
|
protected virtual async Task SynchronizeWithBrokerPositions(Position internalPosition, Position positionForSignal)
|
||||||
List<Position> brokerPositions)
|
|
||||||
{
|
{
|
||||||
// Default implementation: do nothing (for backtest)
|
// Default implementation: do nothing (for backtest)
|
||||||
}
|
}
|
||||||
@@ -1999,11 +1997,6 @@ public abstract class TradingBotBase : ITradingBot
|
|||||||
return position; // Default implementation for backtest
|
return position; // Default implementation for backtest
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual async Task<List<Position>> GetBrokerPositionsForUpdate(Account account)
|
|
||||||
{
|
|
||||||
return new List<Position>(); // Default implementation for backtest
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
protected virtual async Task UpdatePositionWithBrokerData(Position position, List<Position> brokerPositions)
|
||||||
{
|
{
|
||||||
// Default: do nothing for backtest
|
// Default: do nothing for backtest
|
||||||
|
|||||||
Reference in New Issue
Block a user