diff --git a/src/Managing.Application.Abstractions/Grains/ICandleStoreGrain.cs b/src/Managing.Application.Abstractions/Grains/ICandleStoreGrain.cs
index b417a6a0..d42306b9 100644
--- a/src/Managing.Application.Abstractions/Grains/ICandleStoreGrain.cs
+++ b/src/Managing.Application.Abstractions/Grains/ICandleStoreGrain.cs
@@ -14,7 +14,7 @@ public interface ICandleStoreGrain : IGrainWithStringKey
/// Gets the current list of historical candles (up to 500 most recent)
///
/// List of candles ordered by date
- Task> GetCandlesAsync();
+ Task> GetCandlesAsync();
Task GetLastCandle();
}
diff --git a/src/Managing.Application/Abstractions/Grains/IScenarioRunnerGrain.cs b/src/Managing.Application/Abstractions/Grains/IScenarioRunnerGrain.cs
index 20d7dd36..2f05300a 100644
--- a/src/Managing.Application/Abstractions/Grains/IScenarioRunnerGrain.cs
+++ b/src/Managing.Application/Abstractions/Grains/IScenarioRunnerGrain.cs
@@ -1,3 +1,4 @@
+using Managing.Common;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Indicators;
@@ -15,8 +16,9 @@ public interface IScenarioRunnerGrain : IGrainWithGuidKey
///
/// The trading bot configuration
/// Previous signals to consider
- /// Start date
+ /// Trading Exchange
/// The generated signal or null if no signal
- Task GetSignals(TradingBotConfig config, Dictionary previousSignals, DateTime startDate,
- Candle candle);
+ Task GetSignals(TradingBotConfig config, Dictionary previousSignals,
+ Enums.TradingExchanges tradingExchange,
+ Candle lastCandle);
}
\ No newline at end of file
diff --git a/src/Managing.Application/Bots/TradingBotBase.cs b/src/Managing.Application/Bots/TradingBotBase.cs
index 954434f0..fdce0cce 100644
--- a/src/Managing.Application/Bots/TradingBotBase.cs
+++ b/src/Managing.Application/Bots/TradingBotBase.cs
@@ -123,7 +123,7 @@ public class TradingBotBase : ITradingBot
{
var grainKey = CandleHelpers.GetCandleStoreGrainKey(Account.Exchange, Config.Ticker, Config.Timeframe);
var grain = grainFactory.GetGrain(grainKey);
-
+
try
{
// Add a small delay to ensure grain is fully activated
@@ -133,7 +133,7 @@ public class TradingBotBase : ITradingBot
catch (InvalidOperationException ex) when (ex.Message.Contains("invalid activation"))
{
Logger.LogWarning("Grain activation failed for {GrainKey}, retrying in 1 second...", grainKey);
-
+
// Wait a bit longer and retry once
await Task.Delay(1000);
try
@@ -215,7 +215,7 @@ public class TradingBotBase : ITradingBot
await ServiceScopeHelpers.WithScopedService(_scopeFactory, async grainFactory =>
{
var scenarioRunnerGrain = grainFactory.GetGrain(Guid.NewGuid());
- var signal = await scenarioRunnerGrain.GetSignals(Config, Signals, PreloadSince, LastCandle);
+ var signal = await scenarioRunnerGrain.GetSignals(Config, Signals, Account.Exchange, LastCandle);
if (signal == null) return;
await AddSignal(signal);
});
diff --git a/src/Managing.Application/Grains/CandleStoreGrain.cs b/src/Managing.Application/Grains/CandleStoreGrain.cs
index a7554491..f914ca96 100644
--- a/src/Managing.Application/Grains/CandleStoreGrain.cs
+++ b/src/Managing.Application/Grains/CandleStoreGrain.cs
@@ -77,7 +77,7 @@ public class CandleStoreGrain : Grain, ICandleStoreGrain, IAsyncObserver
await base.OnDeactivateAsync(reason, cancellationToken);
}
- public Task> GetCandlesAsync()
+ public Task> GetCandlesAsync()
{
try
{
@@ -86,15 +86,15 @@ public class CandleStoreGrain : Grain, ICandleStoreGrain, IAsyncObserver
{
_logger.LogWarning("State not initialized for grain {GrainKey}, returning empty list",
this.GetPrimaryKeyString());
- return Task.FromResult(new List());
+ return Task.FromResult(new HashSet());
}
- return Task.FromResult(_state.State.Candles.ToList());
+ return Task.FromResult(_state.State.Candles.ToHashSet());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving candles for grain {GrainKey}", this.GetPrimaryKeyString());
- return Task.FromResult(new List());
+ return Task.FromResult(new HashSet());
}
}
@@ -205,7 +205,7 @@ public class CandleStoreGrain : Grain, ICandleStoreGrain, IAsyncObserver
{
try
{
- var streamProvider = this.GetStreamProvider("DefaultStreamProvider");
+ var streamProvider = this.GetStreamProvider("ManagingStreamProvider");
_priceStream = streamProvider.GetStream(streamKey);
_streamSubscription = await _priceStream.SubscribeAsync(this);
diff --git a/src/Managing.Application/Grains/PriceFetcherGrain.cs b/src/Managing.Application/Grains/PriceFetcherGrain.cs
index 7a05bdc3..a1af9523 100644
--- a/src/Managing.Application/Grains/PriceFetcherGrain.cs
+++ b/src/Managing.Application/Grains/PriceFetcherGrain.cs
@@ -171,8 +171,8 @@ public class PriceFetcherGrain : Grain, IPriceFetcherGrain, IRemindable
processedCandles.Count, streamKey);
}
- var streamProvider = this.GetStreamProvider("DefaultStreamProvider");
- var stream = streamProvider.GetStream(streamKey);
+ var streamProvider = this.GetStreamProvider("ManagingStreamProvider");
+ var stream = streamProvider.GetStream("Candles", streamKey);
// Publish to stream (if needed)
foreach (var candle in processedCandles)
diff --git a/src/Managing.Application/Scenarios/ScenarioRunnerGrain.cs b/src/Managing.Application/Scenarios/ScenarioRunnerGrain.cs
index 2bf41d36..3f3f163c 100644
--- a/src/Managing.Application/Scenarios/ScenarioRunnerGrain.cs
+++ b/src/Managing.Application/Scenarios/ScenarioRunnerGrain.cs
@@ -1,5 +1,4 @@
using Managing.Application.Abstractions.Grains;
-using Managing.Application.Abstractions.Services;
using Managing.Core;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
@@ -30,19 +29,17 @@ public class ScenarioRunnerGrain : Grain, IScenarioRunnerGrain
_scopeFactory = scopeFactory;
}
- private async Task> GetCandlesAsync(TradingBotConfig config, DateTime startDate)
+ private async Task> GetCandlesAsync(TradingExchanges tradingExchange, TradingBotConfig config)
{
try
{
- var newCandles = await ServiceScopeHelpers.WithScopedService>(
- _scopeFactory, async exchangeService =>
+ var newCandles = await ServiceScopeHelpers.WithScopedService>(
+ _scopeFactory, async grainFactory =>
{
- return await exchangeService.GetCandlesInflux(
- TradingExchanges.Evm,
- config.Ticker,
- startDate,
- config.Timeframe,
- 500);
+ var priceGrainKey =
+ CandleHelpers.GetCandleStoreGrainKey(tradingExchange, config.Ticker, config.Timeframe);
+ var grain = grainFactory.GetGrain(priceGrainKey);
+ return await grain.GetCandlesAsync();
});
_logger.LogInformation($"Updated {newCandles.Count} candles for {config.Ticker}");
@@ -56,7 +53,7 @@ public class ScenarioRunnerGrain : Grain, IScenarioRunnerGrain
}
public async Task GetSignals(TradingBotConfig config, Dictionary previousSignals,
- DateTime startDate, Candle candle)
+ TradingExchanges tradingExchanges, Candle candle)
{
try
{
@@ -64,7 +61,7 @@ public class ScenarioRunnerGrain : Grain, IScenarioRunnerGrain
// candle, candle.Date, TradingExchanges.Evm, IndicatorType.Composite,
// SignalType.Signal, "Generated Signal");
- var candlesHashSet = await GetCandlesAsync(config, startDate);
+ var candlesHashSet = await GetCandlesAsync(tradingExchanges, config);
if (candlesHashSet.LastOrDefault()!.Date <= candle.Date)
{
return null; // No new candles, no need to generate a signal
diff --git a/src/Managing.Bootstrap/ApiBootstrap.cs b/src/Managing.Bootstrap/ApiBootstrap.cs
index c384f87d..af864de0 100644
--- a/src/Managing.Bootstrap/ApiBootstrap.cs
+++ b/src/Managing.Bootstrap/ApiBootstrap.cs
@@ -321,7 +321,7 @@ public static class ApiBootstrap
}
// Configure Orleans Streams for price data distribution
- siloBuilder.AddMemoryStreams("DefaultStreamProvider")
+ siloBuilder.AddMemoryStreams("ManagingStreamProvider")
.AddMemoryGrainStorage("PubSubStore");
siloBuilder
diff --git a/src/Managing.Domain/Bots/TradingBotConfig.cs b/src/Managing.Domain/Bots/TradingBotConfig.cs
index ad0fc4ae..bb6417db 100644
--- a/src/Managing.Domain/Bots/TradingBotConfig.cs
+++ b/src/Managing.Domain/Bots/TradingBotConfig.cs
@@ -9,38 +9,27 @@ namespace Managing.Domain.Bots;
[GenerateSerializer]
public class TradingBotConfig
{
- [Id(0)]
- [Required] public string AccountName { get; set; }
-
- [Id(1)]
- [Required] public LightMoneyManagement MoneyManagement { get; set; }
-
- [Id(2)]
- [Required] public Ticker Ticker { get; set; }
-
- [Id(3)]
- [Required] public Timeframe Timeframe { get; set; }
-
- [Id(4)]
- [Required] public bool IsForWatchingOnly { get; set; }
-
- [Id(5)]
- [Required] public decimal BotTradingBalance { get; set; }
-
- [Id(6)]
- [Required] public bool IsForBacktest { get; set; }
-
- [Id(7)]
- [Required] public int CooldownPeriod { get; set; }
-
- [Id(8)]
- [Required] public int MaxLossStreak { get; set; }
-
- [Id(9)]
- [Required] public bool FlipPosition { get; set; }
-
- [Id(10)]
- [Required] public string Name { get; set; }
+ [Id(0)] [Required] public string AccountName { get; set; }
+
+ [Id(1)] [Required] public LightMoneyManagement MoneyManagement { get; set; }
+
+ [Id(2)] [Required] public Ticker Ticker { get; set; }
+
+ [Id(3)] [Required] public Timeframe Timeframe { get; set; }
+
+ [Id(4)] [Required] public bool IsForWatchingOnly { get; set; }
+
+ [Id(5)] [Required] public decimal BotTradingBalance { get; set; }
+
+ [Id(6)] [Required] public bool IsForBacktest { get; set; }
+
+ [Id(7)] [Required] public int CooldownPeriod { get; set; }
+
+ [Id(8)] [Required] public int MaxLossStreak { get; set; }
+
+ [Id(9)] [Required] public bool FlipPosition { get; set; }
+
+ [Id(10)] [Required] public string Name { get; set; }
///
/// Risk management configuration for advanced probabilistic analysis and position sizing.