Sviluppo TradingBot
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user