Sviluppo TradingBot

This commit is contained in:
2026-06-09 18:29:41 +02:00
parent 61f1e59964
commit e3c0bd51b2
133 changed files with 24903 additions and 1 deletions
+260
View File
@@ -0,0 +1,260 @@
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Alpaca.Markets;
using DesktopBot.Services;
namespace DesktopBot.ViewModels
{
// ─── BalanceViewModel ────────────────────────────────────────────────────────
public class BalanceViewModel : BaseViewModel
{
private readonly ITradingService _tradingService;
private bool _isLoading;
private string _errorMessage;
private bool _hasError;
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
public string ErrorMessage
{
get => _errorMessage;
set => SetProperty(ref _errorMessage, value);
}
public bool HasError
{
get => _hasError;
set => SetProperty(ref _hasError, value);
}
public ObservableCollection<BalanceRowViewModel> BalanceRows { get; }
= new ObservableCollection<BalanceRowViewModel>();
public ICommand RefreshCommand { get; }
public BalanceViewModel(ITradingService tradingService)
{
_tradingService = tradingService;
RefreshCommand = new RelayCommand(async _ => await LoadAsync());
}
public async Task LoadAsync()
{
IsLoading = true;
HasError = false;
try
{
var account = await _tradingService.GetAccountAsync();
Application.Current.Dispatcher.Invoke(() =>
{
BalanceRows.Clear();
AddSection("Buying Power");
AddRow("RegT Buying Power", account.RegulationBuyingPower, account.RegulationBuyingPower);
AddRow("Day Trading Buying Power", account.DayTradingBuyingPower, account.DayTradingBuyingPower);
AddRow("Effective Buying Power", account.BuyingPower, account.BuyingPower);
AddRow("Non-Marginable Buying Power", account.NonMarginableBuyingPower, account.NonMarginableBuyingPower);
AddSection("Margin");
AddRow("Initial Margin", account.InitialMargin, account.InitialMargin);
AddRow("Maintenance Margin", account.MaintenanceMargin, account.MaintenanceMargin);
AddSection("Cash");
AddRow("Cash", account.TradableCash, account.TradableCash);
AddSection("Positions");
AddRow("Equity", account.LastEquity, account.Equity ?? 0m, bold: true);
AddRow("Long Market Value", account.LongMarketValue, account.LongMarketValue);
AddRow("Short Market Value", account.ShortMarketValue, account.ShortMarketValue);
});
}
catch (Exception ex)
{
Application.Current.Dispatcher.Invoke(() =>
{
HasError = true;
ErrorMessage = "Errore: " + ex.Message;
});
}
finally
{
Application.Current.Dispatcher.Invoke(() => IsLoading = false);
}
}
private void AddSection(string title)
=> BalanceRows.Add(new BalanceRowViewModel { Label = title, IsSection = true });
private void AddRow(string label, decimal? last, decimal? curr, bool bold = false)
=> BalanceRows.Add(new BalanceRowViewModel
{
Label = label,
LastClose = last.HasValue ? "$" + last.Value.ToString("N2") : "-",
Current = curr.HasValue ? "$" + curr.Value.ToString("N2") : "-",
IsBold = bold
});
private void AddRow(string label, decimal last, decimal curr, bool bold = false)
=> BalanceRows.Add(new BalanceRowViewModel
{
Label = label,
LastClose = "$" + last.ToString("N2"),
Current = "$" + curr.ToString("N2"),
IsBold = bold
});
}
// ─── PositionsViewModel ──────────────────────────────────────────────────────
public class PositionsViewModel : BaseViewModel
{
private readonly ITradingService _tradingService;
private bool _isLoading;
private string _errorMessage;
private bool _hasError;
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
public string ErrorMessage
{
get => _errorMessage;
set => SetProperty(ref _errorMessage, value);
}
public bool HasError
{
get => _hasError;
set => SetProperty(ref _hasError, value);
}
public ObservableCollection<PositionViewModel> Positions { get; }
= new ObservableCollection<PositionViewModel>();
public ICommand RefreshCommand { get; }
public ICommand CloseAllCommand { get; }
public ICommand ClosePositionCommand { get; }
public PositionsViewModel(ITradingService tradingService)
{
_tradingService = tradingService;
RefreshCommand = new RelayCommand(async _ => await LoadAsync());
CloseAllCommand = new RelayCommand(async _ =>
{
await _tradingService.CloseAllPositionsAsync();
await LoadAsync();
});
ClosePositionCommand = new RelayCommand(async p =>
{
if (p is string symbol)
{
await _tradingService.ClosePositionAsync(symbol);
await LoadAsync();
}
});
}
public async Task LoadAsync()
{
IsLoading = true;
HasError = false;
try
{
var positions = await _tradingService.GetAllPositionsAsync();
Application.Current.Dispatcher.Invoke(() =>
{
Positions.Clear();
foreach (var p in positions)
Positions.Add(new PositionViewModel(p));
});
}
catch (Exception ex)
{
Application.Current.Dispatcher.Invoke(() =>
{
HasError = true;
ErrorMessage = "Errore: " + ex.Message;
});
}
finally
{
Application.Current.Dispatcher.Invoke(() => IsLoading = false);
}
}
}
// ─── OrdersViewModel ────────────────────────────────────────────────────────
public class OrdersViewModel : BaseViewModel
{
private readonly ITradingService _tradingService;
private bool _isLoading;
private string _errorMessage;
private bool _hasError;
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
public string ErrorMessage
{
get => _errorMessage;
set => SetProperty(ref _errorMessage, value);
}
public bool HasError
{
get => _hasError;
set => SetProperty(ref _hasError, value);
}
public ObservableCollection<OrderViewModel> Orders { get; }
= new ObservableCollection<OrderViewModel>();
public ICommand RefreshCommand { get; }
public ICommand CancelOrderCommand { get; }
public OrdersViewModel(ITradingService tradingService)
{
_tradingService = tradingService;
RefreshCommand = new RelayCommand(async _ => await LoadAsync());
CancelOrderCommand = new RelayCommand(async p =>
{
if (p is Guid id)
{
await _tradingService.CancelOrderAsync(id);
await LoadAsync();
}
});
}
public async Task LoadAsync()
{
IsLoading = true;
HasError = false;
try
{
var orders = await _tradingService.GetOrdersAsync(OrderStatusFilter.All, 100);
Application.Current.Dispatcher.Invoke(() =>
{
Orders.Clear();
foreach (var o in orders)
Orders.Add(new OrderViewModel(o));
});
}
catch (Exception ex)
{
Application.Current.Dispatcher.Invoke(() =>
{
HasError = true;
ErrorMessage = "Errore: " + ex.Message;
});
}
finally
{
Application.Current.Dispatcher.Invoke(() => IsLoading = false);
}
}
}
}