Sviluppo TradingBot
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using DesktopBot.Services;
|
||||
|
||||
namespace DesktopBot.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// ViewModel per il Wallet e le posizioni aperte
|
||||
/// </summary>
|
||||
public class WalletViewModel : BaseViewModel
|
||||
{
|
||||
private readonly ITradingService _tradingService;
|
||||
|
||||
private decimal _equity;
|
||||
private bool _isLoading;
|
||||
private string _errorMessage;
|
||||
private bool _hasError;
|
||||
private ObservableCollection<PositionViewModel> _positions = new ObservableCollection<PositionViewModel>();
|
||||
|
||||
public decimal Equity
|
||||
{
|
||||
get => _equity;
|
||||
set => SetProperty(ref _equity, value);
|
||||
}
|
||||
|
||||
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 => _positions;
|
||||
set => SetProperty(ref _positions, value);
|
||||
}
|
||||
|
||||
public ICommand RefreshCommand { get; }
|
||||
public ICommand CloseAllCommand { get; }
|
||||
|
||||
public WalletViewModel(ITradingService tradingService)
|
||||
{
|
||||
_tradingService = tradingService;
|
||||
RefreshCommand = new RelayCommand(async _ => await RefreshAsync());
|
||||
CloseAllCommand = new RelayCommand(async _ => await CloseAllPositionsAsync());
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task RefreshAsync()
|
||||
{
|
||||
await LoadAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica equity e posizioni aperte da Alpaca
|
||||
/// </summary>
|
||||
public async System.Threading.Tasks.Task LoadAsync()
|
||||
{
|
||||
IsLoading = true;
|
||||
HasError = false;
|
||||
try
|
||||
{
|
||||
var accountTask = _tradingService.GetAccountAsync();
|
||||
var positionsTask = _tradingService.GetAllPositionsAsync();
|
||||
|
||||
await System.Threading.Tasks.Task.WhenAll(accountTask, positionsTask);
|
||||
|
||||
var account = accountTask.Result;
|
||||
var positions = positionsTask.Result;
|
||||
|
||||
Application.Current?.Dispatcher.Invoke(() =>
|
||||
{
|
||||
Equity = account.Equity ?? 0m;
|
||||
Positions.Clear();
|
||||
foreach (var pos in positions)
|
||||
Positions.Add(new PositionViewModel(pos));
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.Current?.Dispatcher.Invoke(() =>
|
||||
{
|
||||
HasError = true;
|
||||
ErrorMessage = "Errore: " + ex.Message;
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
Application.Current?.Dispatcher.Invoke(() => IsLoading = false);
|
||||
}
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task CloseAllPositionsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await _tradingService.CloseAllPositionsAsync();
|
||||
await RefreshAsync();
|
||||
}
|
||||
catch { /* Gestito silenziosamente */ }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ViewModel per una singola posizione aperta
|
||||
/// </summary>
|
||||
public class PositionViewModel : BaseViewModel
|
||||
{
|
||||
public string Symbol { get; }
|
||||
public decimal Quantity { get; }
|
||||
public string Side { get; }
|
||||
public decimal EntryPrice { get; }
|
||||
public decimal CurrentPrice { get; }
|
||||
public decimal MarketValue { get; }
|
||||
public decimal UnrealizedPnL { get; }
|
||||
public decimal UnrealizedPnLPercent { get; }
|
||||
public bool IsProfit { get; }
|
||||
|
||||
public PositionViewModel(Alpaca.Markets.IPosition position)
|
||||
{
|
||||
Symbol = position.Symbol;
|
||||
Quantity = Math.Abs(position.Quantity);
|
||||
Side = position.Quantity >= 0 ? "LONG" : "SHORT";
|
||||
EntryPrice = position.AverageEntryPrice;
|
||||
CurrentPrice = position.AssetCurrentPrice ?? 0m;
|
||||
MarketValue = position.MarketValue ?? 0m;
|
||||
UnrealizedPnL = position.UnrealizedProfitLoss ?? 0m;
|
||||
var cost = position.CostBasis != 0 ? position.CostBasis : 1m;
|
||||
UnrealizedPnLPercent = (cost != 0) ? (UnrealizedPnL / Math.Abs(cost)) * 100m : 0m;
|
||||
IsProfit = UnrealizedPnL >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user