Sviluppo TradingBot
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using DesktopBot.Engine;
|
||||
using DesktopBot.Models;
|
||||
using DesktopBot.Services;
|
||||
namespace DesktopBot.ViewModels
|
||||
{
|
||||
public class MainViewModel : BaseViewModel
|
||||
{
|
||||
private readonly ITradingService _tradingService;
|
||||
private readonly AutomatedBotEngine _botEngine;
|
||||
private readonly AlpacaPingService _pingService;
|
||||
|
||||
public PingViewModel PingVM { get; } = new PingViewModel();
|
||||
|
||||
// ── Auto-refresh periodico ─────────────────────────────────────────
|
||||
/// <summary>Intervallo (secondi) per l'aggiornamento frequente: posizioni e ordini.</summary>
|
||||
private const int FastRefreshSeconds = 30;
|
||||
/// <summary>Intervallo (secondi) per l'aggiornamento lento: balance, wallet, dashboard.</summary>
|
||||
private const int SlowRefreshSeconds = 60;
|
||||
|
||||
private CancellationTokenSource _autoRefreshCts;
|
||||
private int _refreshCycle; // contatore cicli per sfalsare il refresh lento
|
||||
|
||||
private BaseViewModel _currentViewModel;
|
||||
private string _selectedTab;
|
||||
|
||||
public DashboardViewModel DashboardVM { get; }
|
||||
public BotsManagerViewModel BotsVM { get; }
|
||||
public LiveLogViewModel LiveLogVM { get; }
|
||||
public WalletViewModel WalletVM { get; }
|
||||
public SettingsViewModel SettingsVM { get; }
|
||||
public BalanceViewModel BalanceVM { get; }
|
||||
public PositionsViewModel PositionsVM { get; }
|
||||
public OrdersViewModel OrdersVM { get; }
|
||||
|
||||
public BaseViewModel CurrentViewModel
|
||||
{
|
||||
get => _currentViewModel;
|
||||
set => SetProperty(ref _currentViewModel, value);
|
||||
}
|
||||
|
||||
public string SelectedTab
|
||||
{
|
||||
get => _selectedTab;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedTab, value))
|
||||
NavigateToTab(value);
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand NavigateCommand { get; }
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
_tradingService = new AlpacaTradingService();
|
||||
_botEngine = new AutomatedBotEngine(_tradingService);
|
||||
_pingService = new AlpacaPingService();
|
||||
_pingService.PingCompleted += (_, r) => PingVM.Update(r);
|
||||
|
||||
DashboardVM = new DashboardViewModel(_tradingService, _botEngine);
|
||||
BotsVM = new BotsManagerViewModel(_tradingService);
|
||||
LiveLogVM = new LiveLogViewModel(_botEngine);
|
||||
WalletVM = new WalletViewModel(_tradingService);
|
||||
SettingsVM = new SettingsViewModel(_tradingService, OnCredentialsSaved);
|
||||
BalanceVM = new BalanceViewModel(_tradingService);
|
||||
PositionsVM = new PositionsViewModel(_tradingService);
|
||||
OrdersVM = new OrdersViewModel(_tradingService);
|
||||
|
||||
NavigateCommand = new RelayCommand(param => SelectedTab = param?.ToString());
|
||||
SubscribeToBotEvents();
|
||||
|
||||
var saved = CredentialService.LoadCredentials();
|
||||
if (saved != null)
|
||||
{
|
||||
_tradingService.Initialize(saved.ApiKey, saved.ApiSecret, saved.IsPaper);
|
||||
_pingService.SetEnvironment(saved.IsPaper);
|
||||
_pingService.Start(10);
|
||||
CurrentViewModel = DashboardVM;
|
||||
SelectedTab = "Dashboard";
|
||||
_ = LoadInitialDataAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentViewModel = SettingsVM;
|
||||
SelectedTab = "Settings";
|
||||
}
|
||||
}
|
||||
|
||||
private void NavigateToTab(string tabName)
|
||||
{
|
||||
CurrentViewModel = tabName switch
|
||||
{
|
||||
"Dashboard" => (BaseViewModel)DashboardVM,
|
||||
"Bot" => BotsVM,
|
||||
"LiveLog" => LiveLogVM,
|
||||
"Wallet" => WalletVM,
|
||||
"Settings" => SettingsVM,
|
||||
"Balance" => BalanceVM,
|
||||
"Positions" => PositionsVM,
|
||||
"Orders" => OrdersVM,
|
||||
_ => DashboardVM
|
||||
};
|
||||
}
|
||||
|
||||
private void SubscribeToBotEvents()
|
||||
{
|
||||
_botEngine.LogGenerated += (sender, log) => LiveLogVM.AddLog(log);
|
||||
_botEngine.EquityUpdated += (sender, equity) => DashboardVM.UpdateEquity(equity);
|
||||
}
|
||||
|
||||
private async Task LoadInitialDataAsync()
|
||||
{
|
||||
await Task.WhenAll(
|
||||
DashboardVM.LoadAsync(),
|
||||
WalletVM.LoadAsync(),
|
||||
BalanceVM.LoadAsync(),
|
||||
PositionsVM.LoadAsync(),
|
||||
OrdersVM.LoadAsync()
|
||||
);
|
||||
StartAutoRefresh();
|
||||
}
|
||||
|
||||
// ── Auto-refresh periodico ─────────────────────────────────────────
|
||||
private void StartAutoRefresh()
|
||||
{
|
||||
_autoRefreshCts?.Cancel();
|
||||
_autoRefreshCts = new CancellationTokenSource();
|
||||
_refreshCycle = 0;
|
||||
_ = AutoRefreshLoopAsync(_autoRefreshCts.Token);
|
||||
}
|
||||
|
||||
private async Task AutoRefreshLoopAsync(CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(FastRefreshSeconds), ct);
|
||||
if (ct.IsCancellationRequested) break;
|
||||
|
||||
_refreshCycle++;
|
||||
|
||||
// Refresh frequente: posizioni aperte e ordini recenti
|
||||
var fastTasks = new System.Collections.Generic.List<Task>
|
||||
{
|
||||
SafeRefresh(PositionsVM.LoadAsync),
|
||||
SafeRefresh(OrdersVM.LoadAsync)
|
||||
};
|
||||
|
||||
// Refresh lento (ogni 2 cicli = 60s): balance, wallet, dashboard
|
||||
if (_refreshCycle % 2 == 0)
|
||||
{
|
||||
fastTasks.Add(SafeRefresh(BalanceVM.LoadAsync));
|
||||
fastTasks.Add(SafeRefresh(WalletVM.LoadAsync));
|
||||
fastTasks.Add(SafeRefresh(DashboardVM.LoadAsync));
|
||||
}
|
||||
|
||||
await Task.WhenAll(fastTasks);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) { /* atteso */ }
|
||||
}
|
||||
|
||||
private static async Task SafeRefresh(Func<Task> loader)
|
||||
{
|
||||
try { await loader(); }
|
||||
catch { /* non bloccare il ciclo per errori singoli di rete */ }
|
||||
}
|
||||
|
||||
private void OnCredentialsSaved(string apiKey, string apiSecret, bool isPaper)
|
||||
{
|
||||
SelectedTab = "Dashboard";
|
||||
_ = LoadInitialDataAsync();
|
||||
}
|
||||
public void InitializeWithCredentials(string apiKey, string apiSecret, bool isPaper)
|
||||
{
|
||||
_tradingService.Initialize(apiKey, apiSecret, isPaper);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user