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
+115
View File
@@ -0,0 +1,115 @@
<UserControl x:Class="DesktopBot.Views.BalanceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="ColHeader" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Padding" Value="10,8"/>
</Style>
<Style x:Key="GridCell" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="10,6"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</UserControl.Resources>
<Grid Background="{StaticResource BackgroundDarkBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Header -->
<Grid Grid.Row="0" Margin="24,20,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Balance" Style="{StaticResource SectionTitle}" Margin="0"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="Caricamento..." Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="12" VerticalAlignment="Center" Margin="0,0,12,0"
Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisConverter}}"/>
<Button Content="&#8635; Aggiorna" Command="{Binding RefreshCommand}"
Style="{StaticResource OutlineButton}" Padding="14,7"/>
</StackPanel>
</Grid>
<!-- Sottotitolo colonne -->
<TextBlock Grid.Row="1" Margin="24,8,24,0"
Text="Panoramica completa del bilancio del conto Alpaca"
Style="{StaticResource LabelSecondary}"/>
<!-- Errore -->
<Border Grid.Row="2" Margin="24,10,24,0"
Background="#2A1515" BorderBrush="{StaticResource AccentRedBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,8"
Visibility="{Binding HasError, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="{Binding ErrorMessage}" Foreground="{StaticResource AccentRedBrush}"
FontFamily="Segoe UI" FontSize="12"/>
</Border>
<!-- Intestazione colonne -->
<Grid Grid.Row="3" Margin="24,14,24,0"
Background="{StaticResource BackgroundPanelBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Voce" Style="{StaticResource ColHeader}"/>
<TextBlock Grid.Column="1" Text="Ultima Chiusura" Style="{StaticResource ColHeader}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="2" Text="Corrente" Style="{StaticResource ColHeader}" HorizontalAlignment="Right" Padding="10,8,20,8"/>
</Grid>
<!-- Righe -->
<ScrollViewer Grid.Row="4" Margin="24,0,24,20" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding BalanceRows}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1">
<Grid>
<!-- Sezione -->
<TextBlock Text="{Binding Label}"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="Bold"
Padding="10,10,10,4" Background="{StaticResource BackgroundDarkBrush}"
Visibility="{Binding IsSection, Converter={StaticResource BoolToVisConverter}}"/>
<!-- Riga dati -->
<Grid Visibility="{Binding IsSection, Converter={StaticResource InverseBoolConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Label}" Padding="24,6,10,6">
<TextBlock.Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource GridCell}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsBold}" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Grid.Column="1" Text="{Binding LastClose}"
Style="{StaticResource GridCell}" HorizontalAlignment="Right"
Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBlock Grid.Column="2" Text="{Binding Current}"
Style="{StaticResource GridCell}" HorizontalAlignment="Right" Padding="10,6,20,6"/>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
+8
View File
@@ -0,0 +1,8 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class BalanceView : UserControl
{
public BalanceView() { InitializeComponent(); }
}
}
+245
View File
@@ -0,0 +1,245 @@
<UserControl x:Class="DesktopBot.Views.BotConfigView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:DesktopBot.Models"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary Source="/DesktopBot;component/Themes/DarkTheme.xaml"/>
</UserControl.Resources>
<ScrollViewer Background="{StaticResource BackgroundDarkBrush}"
VerticalScrollBarVisibility="Auto">
<Grid Margin="32">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Titolo -->
<TextBlock Grid.Row="0"
Text="Configurazione Bot"
Style="{StaticResource SectionTitle}"/>
<!-- Banner di avviso: Bot bloccato -->
<Border Grid.Row="0"
Margin="0,60,0,16"
Background="#FFD700"
BorderBrush="#FFA500"
BorderThickness="2"
CornerRadius="6"
Padding="16,12"
Visibility="{Binding IsAssetLocked, Converter={StaticResource BoolVisibilityConverter}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="🔒"
FontSize="24"
Margin="0,0,12,0"
VerticalAlignment="Center"/>
<StackPanel Grid.Column="1">
<TextBlock Text="BOT BLOCCATO"
FontSize="14"
FontWeight="Bold"
Foreground="#000000"/>
<TextBlock TextWrapping="Wrap"
Foreground="#333333"
FontSize="12"
Margin="0,4,0,0">
Questo bot è associato in modo permanente a
<Bold><Run Text="{Binding Symbol, Mode=OneWay}"/></Bold>
con strategia
<Bold><Run Text="{Binding Config.Strategy, Mode=OneWay}"/></Bold>.
Asset e strategia non possono essere modificati.
<LineBreak/>
<Run FontStyle="Italic">Bloccato il: </Run>
<Run Text="{Binding LockedAtLabel, Mode=OneWay}" FontStyle="Italic"/>
</TextBlock>
</StackPanel>
</Grid>
</Border>
<!-- Sezione Simbolo e Quantità -->
<Border Grid.Row="1" Style="{StaticResource Card}" Margin="0,0,0,16">
<StackPanel>
<TextBlock Text="ASSET E POSIZIONE"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,16"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Simbolo -->
<StackPanel Grid.Column="0">
<TextBlock Text="Simbolo Ticker"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<TextBox Style="{StaticResource DarkTextBox}"
Text="{Binding Config.Symbol, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding IsAssetLocked, Converter={StaticResource InverseBoolConverter}}"/>
<TextBlock Text="⚠ Campo bloccato: il bot è associato a questo asset"
Style="{StaticResource LabelSecondary}"
Foreground="#FFC107"
FontSize="11"
Margin="0,4,0,0"
Visibility="{Binding IsAssetLocked, Converter={StaticResource BoolVisibilityConverter}}"/>
</StackPanel>
<!-- Quantità -->
<StackPanel Grid.Column="2">
<TextBlock Text="Quantità (Azioni)"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<TextBox Style="{StaticResource DarkTextBox}"
Text="{Binding Config.Quantity, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Grid>
</StackPanel>
</Border>
<!-- Sezione Strategia -->
<Border Grid.Row="2" Style="{StaticResource Card}" Margin="0,0,0,16">
<StackPanel>
<TextBlock Text="STRATEGIA DI TRADING"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,16"/>
<!-- Selezione Strategia -->
<StackPanel Margin="0,0,0,16">
<TextBlock Text="Tipo di Strategia"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<ComboBox Style="{StaticResource DarkComboBox}"
SelectedItem="{Binding Config.Strategy}"
IsEnabled="{Binding IsConfigLocked, Converter={StaticResource InverseBoolConverter}}">
<ComboBoxItem Content="EMA_CROSSOVER"/>
<ComboBoxItem Content="RSI"/>
<ComboBoxItem Content="MACD"/>
</ComboBox>
<TextBlock Text="⚠ Strategia bloccata: ottimizzata per questo asset"
Style="{StaticResource LabelSecondary}"
Foreground="#FFC107"
FontSize="11"
Margin="0,4,0,0"
Visibility="{Binding IsConfigLocked, Converter={StaticResource BoolVisibilityConverter}}"/>
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- EMA Veloce -->
<StackPanel Grid.Column="0">
<TextBlock Text="EMA Veloce (periodo)"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<TextBox Style="{StaticResource DarkTextBox}"
Text="{Binding Config.FastEmaPeriod}"/>
</StackPanel>
<!-- EMA Lenta -->
<StackPanel Grid.Column="2">
<TextBlock Text="EMA Lenta (periodo)"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<TextBox Style="{StaticResource DarkTextBox}"
Text="{Binding Config.SlowEmaPeriod}"/>
</StackPanel>
</Grid>
</StackPanel>
</Border>
<!-- Sezione Gestione Rischio -->
<Border Grid.Row="3" Style="{StaticResource Card}" Margin="0,0,0,16">
<StackPanel>
<TextBlock Text="GESTIONE DEL RISCHIO"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,16"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Stop Loss -->
<StackPanel Grid.Column="0">
<TextBlock Text="Stop Loss %"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<TextBox Style="{StaticResource DarkTextBox}"
Text="{Binding Config.StopLossPercentage, StringFormat={}{0:P0}}"/>
<TextBlock Text="Es: 0.02 = 2%"
Style="{StaticResource LabelSecondary}"
Margin="0,4,0,0"/>
</StackPanel>
<!-- Take Profit -->
<StackPanel Grid.Column="2">
<TextBlock Text="Take Profit %"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<TextBox Style="{StaticResource DarkTextBox}"
Text="{Binding Config.TakeProfitPercentage, StringFormat={}{0:P0}}"/>
<TextBlock Text="Es: 0.05 = 5%"
Style="{StaticResource LabelSecondary}"
Margin="0,4,0,0"/>
</StackPanel>
<!-- Intervallo Check -->
<StackPanel Grid.Column="4">
<TextBlock Text="Intervallo (sec)"
Style="{StaticResource LabelSecondary}"
Margin="0,0,0,6"/>
<TextBox Style="{StaticResource DarkTextBox}"
Text="{Binding Config.CheckIntervalSeconds}"/>
<TextBlock Text="Ogni quanti secondi analizzare"
Style="{StaticResource LabelSecondary}"
Margin="0,4,0,0"/>
</StackPanel>
</Grid>
<!-- Pulsanti Start / Stop -->
<StackPanel Orientation="Horizontal" Margin="0,24,0,0" HorizontalAlignment="Right">
<Button Content="▶ AVVIA BOT"
Style="{StaticResource PrimaryButton}"
Command="{Binding StartBotCommand}"
Margin="0,0,12,0"
Padding="24,12"/>
<Button Content="■ FERMA BOT"
Style="{StaticResource DangerButton}"
Command="{Binding StopBotCommand}"
Padding="24,12"/>
</StackPanel>
<!-- Messaggio di Stato -->
<TextBlock Text="{Binding StatusMessage}"
Style="{StaticResource LabelSecondary}"
HorizontalAlignment="Right"
Margin="0,12,0,0"
FontStyle="Italic"/>
</StackPanel>
</Border>
</Grid>
</ScrollViewer>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class BotConfigView : UserControl
{
public BotConfigView()
{
InitializeComponent();
}
}
}
+477
View File
@@ -0,0 +1,477 @@
<UserControl x:Class="DesktopBot.Views.BotsManagerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:DesktopBot.ViewModels"
xmlns:ctrl="clr-namespace:DesktopBot.Controls"
xmlns:models="clr-namespace:DesktopBot.Models"
xmlns:cvt="clr-namespace:DesktopBot.Converters"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/DesktopBot;component/Themes/DarkTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
<cvt:MaxItemsConverter x:Key="MaxItemsConverter"/>
</ResourceDictionary>
</UserControl.Resources>
<Grid Background="{StaticResource BackgroundDarkBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- HEADER: titolo + status + pulsante start/stop -->
<Border Grid.Row="0" Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1"
Padding="28,14">
<Grid DataContext="{Binding BtcBot}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Logo BTC -->
<Grid Grid.Column="0" Width="44" Height="44" Margin="0,0,16,0">
<Ellipse><Ellipse.Fill><SolidColorBrush Color="#F7931A"/></Ellipse.Fill></Ellipse>
<TextBlock Text="BTC" FontFamily="Consolas" FontSize="11" FontWeight="Bold"
Foreground="#0E0E14" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<!-- Titolo + badge stato -->
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="BOT TRADING" Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI" FontSize="9" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,10,0"/>
<!-- Dot stato -->
<Ellipse Width="7" Height="7" VerticalAlignment="Center" Margin="0,0,5,0">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="{StaticResource TextSecondaryBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRunning}" Value="True">
<Setter Property="Fill" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<TextBlock VerticalAlignment="Center" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="INATTIVO"/>
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRunning}" Value="True">
<Setter Property="Text" Value="IN ESECUZIONE"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
<TextBlock Text="Bitcoin / US Dollar" Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="16" FontWeight="SemiBold" Margin="0,2,0,0"/>
</StackPanel>
<!-- Pulsante Start / Stop -->
<Button Grid.Column="3" Width="130" Height="44"
Command="{Binding ToggleRunCommand}" Cursor="Hand" VerticalAlignment="Center">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Foreground" Value="#0E0E14"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" CornerRadius="8" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsRunning}" Value="False">
<Setter Property="Background" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="Content" Value="&#x25BA; AVVIA"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsRunning}" Value="True">
<Setter Property="Background" Value="{StaticResource AccentRedBrush}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Content" Value="&#x25A0; FERMA"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Border>
<!--
CONTENUTO PRINCIPALE (scrollabile)
-->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="340"/>
</Grid.ColumnDefinitions>
<!-- COLONNA SINISTRA: grafico + log -->
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- GRAFICO PREZZI -->
<Border Grid.Row="0" Style="{StaticResource Card}" Margin="16,16,8,8"
DataContext="{Binding ChartVM}">
<StackPanel>
<Grid Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="GRAFICO PREZZI" Style="{StaticResource LabelSecondary}" VerticalAlignment="Center"/>
<TextBlock Text=" ? BTC/USD ? 1min" Foreground="#F7931A"
FontFamily="Consolas" FontSize="10" VerticalAlignment="Center" Margin="4,0,0,0"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{Binding CurrentPrice, StringFormat={}{0:N2}}"
Foreground="White" FontFamily="Consolas" FontSize="18" FontWeight="Bold" Margin="0,0,8,0"/>
<TextBlock FontFamily="Consolas" FontSize="12" VerticalAlignment="Center"
Foreground="{Binding PriceChangeBrush}"
Text="{Binding PriceChangePercent, StringFormat={}{0:+0.00;-0.00;0.00}%}"/>
</StackPanel>
</Grid>
<ctrl:PriceLineChart PriceData="{Binding PriceData}" LineColor="#00E676"
Height="240" HorizontalAlignment="Stretch"/>
<TextBlock Text="{Binding StatusMessage}" Style="{StaticResource LabelSecondary}"
FontSize="9" Margin="0,5,0,0" FontStyle="Italic"/>
</StackPanel>
</Border>
<!-- LOG OPERATIVO (espanso, riempie lo spazio rimanente) -->
<Border Grid.Row="1" Style="{StaticResource Card}" Margin="16,0,8,16"
DataContext="{Binding BtcBot}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Header log -->
<Grid Grid.Row="0" Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="LOG OPERATIVO"
Style="{StaticResource LabelSecondary}" VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button Content="&#x1F4CB; Copia"
Command="{Binding CopyLogCommand}"
Style="{StaticResource OutlineButton}"
Padding="10,2" Margin="0,0,6,0"
ToolTip="Copia tutti i log negli appunti"/>
<Border CornerRadius="3" Padding="6,2" Background="{StaticResource NavActiveBrush}">
<TextBlock Text="{Binding BotLog.Count, StringFormat={}{0} eventi}"
Style="{StaticResource LabelSecondary}" FontSize="10"/>
</Border>
</StackPanel>
</Grid>
<!-- Corpo log -->
<Border Grid.Row="1" Background="{StaticResource BackgroundDarkBrush}" CornerRadius="5" Padding="0">
<ListView ItemsSource="{Binding BotLog}" ScrollViewer.VerticalScrollBarVisibility="Auto" BorderThickness="0" Background="Transparent">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="8,4"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type models:BotLogEntry}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="76"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Timestamp, StringFormat='dd-MM-yyyy HH:mm:ss'}" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Consolas" FontSize="11" VerticalAlignment="Center"/>
<Border Grid.Column="1" CornerRadius="3" Padding="6,2" Margin="0,0,10,0" HorizontalAlignment="Left" VerticalAlignment="Center">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="#FF3A3A4A"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Level}" Value="Success"><Setter Property="Background" Value="#1A00E676"/></DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Error"><Setter Property="Background" Value="#1AFF1744"/></DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Warning"><Setter Property="Background" Value="#1AFFC107"/></DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="{Binding Level}" FontFamily="Consolas" FontSize="10" FontWeight="Bold" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Level}" Value="Success"><Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/></DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Error"><Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/></DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Warning"><Setter Property="Foreground" Value="#FFFFC107"/></DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
<TextBlock Grid.Column="2" Text="{Binding Message}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Consolas" FontSize="11" TextTrimming="CharacterEllipsis" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Border>
</Grid>
</Border>
</Grid>
<!-- COLONNA DESTRA: posizioni + storico -->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- POSIZIONI APERTE -->
<Border Grid.Row="0" Style="{StaticResource Card}" Margin="8,16,16,8"
DataContext="{Binding BtcBot}">
<StackPanel>
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="POSIZIONI APERTE"
Style="{StaticResource LabelSecondary}" VerticalAlignment="Center"/>
<Border Grid.Column="1" CornerRadius="3" Padding="6,2" Background="{StaticResource NavActiveBrush}">
<TextBlock Text="{Binding OpenPositions.Count}" Style="{StaticResource LabelSecondary}" FontSize="10"/>
</Border>
</Grid>
<!-- Nessuna posizione -->
<TextBlock Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI"
FontSize="11" FontStyle="Italic" Padding="4,6" Text="Nessuna posizione aperta">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding OpenPositions.Count}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ItemsControl ItemsSource="{Binding OpenPositions}" MaxHeight="180">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{StaticResource BackgroundDarkBrush}" CornerRadius="5"
Padding="10,8" Margin="0,0,0,4">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<StackPanel Orientation="Horizontal">
<Border CornerRadius="3" Padding="5,2" Margin="0,0,6,0">
<Border.Background><SolidColorBrush Color="#1A3A2A"/></Border.Background>
<TextBlock Text="{Binding Side}" FontSize="10" FontWeight="Bold"
Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI"/>
</Border>
<TextBlock Text="{Binding Symbol}" Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Consolas" FontSize="12" FontWeight="Bold" VerticalAlignment="Center"/>
</StackPanel>
<TextBlock Margin="0,4,0,0" Style="{StaticResource LabelSecondary}" FontSize="10">
<Run Text="Entry: "/>
<Run Text="{Binding EntryPrice, StringFormat={}{0:N2}}" Foreground="White"/>
<Run Text=" SL: "/>
<Run Text="{Binding StopLoss, StringFormat={}{0:N2}}" Foreground="{StaticResource AccentRedBrush}"/>
<Run Text=" TP: "/>
<Run Text="{Binding TakeProfit, StringFormat={}{0:N2}}" Foreground="{StaticResource AccentGreenBrush}"/>
</TextBlock>
<TextBlock Text="{Binding OpenedAt, StringFormat=Aperta: {}{0:HH:mm dd/MM}}"
Style="{StaticResource LabelSecondary}" FontSize="9" Margin="0,2,0,0"/>
</StackPanel>
<Border Grid.Column="1" CornerRadius="3" Padding="5,2" VerticalAlignment="Center">
<Border.Background><SolidColorBrush Color="#1A3A2A"/></Border.Background>
<TextBlock Text="{Binding Confidence, StringFormat=Conf: {}{0}%}"
FontSize="10" Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI"/>
</Border>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
<!-- STORICO TRADE -->
<Border Grid.Row="1" Style="{StaticResource Card}" Margin="8,0,16,16"
DataContext="{Binding BtcBot}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="STORICO TRADE"
Style="{StaticResource LabelSecondary}" Margin="0,0,0,10"/>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<!-- Nessun trade -->
<StackPanel>
<TextBlock Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI"
FontSize="11" FontStyle="Italic" Padding="4,6" Text="Nessun trade registrato">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding TradeHistory.Count}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ItemsControl ItemsSource="{Binding TradeHistory, Converter={StaticResource MaxItemsConverter}, ConverterParameter=50}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border CornerRadius="5" Padding="10,7" Margin="0,0,0,4">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{StaticResource BackgroundDarkBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PnLCategory}" Value="profit">
<Setter Property="Background" Value="#0D2E1A"/>
</DataTrigger>
<DataTrigger Binding="{Binding PnLCategory}" Value="loss">
<Setter Property="Background" Value="#2E0D0D"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Side}" FontSize="10" FontWeight="Bold"
FontFamily="Segoe UI" VerticalAlignment="Center" Margin="0,0,8,0">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Side}" Value="SELL">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text="{Binding Symbol}" Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Consolas" FontSize="11" FontWeight="Bold" VerticalAlignment="Center"/>
</StackPanel>
<TextBlock Margin="0,3,0,0" Style="{StaticResource LabelSecondary}" FontSize="10">
<Run Text="{Binding EntryPrice, StringFormat=In: {}{0:N2}}"/>
<Run Text=" &#x2192; "/>
<Run Text="{Binding ExitPrice, StringFormat={}{0:N2}}" Foreground="White"/>
</TextBlock>
<TextBlock Text="{Binding ClosedAt, StringFormat={}{0:HH:mm dd/MM}}"
Style="{StaticResource LabelSecondary}" FontSize="9" Margin="0,2,0,0"/>
</StackPanel>
<!-- Badge PnL -->
<Border Grid.Column="1" CornerRadius="4" Padding="8,4" VerticalAlignment="Center">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="#1A3A2A"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PnLCategory}" Value="loss">
<Setter Property="Background" Value="#3A1A1A"/>
</DataTrigger>
<DataTrigger Binding="{Binding PnLCategory}" Value="open">
<Setter Property="Background" Value="#1A1A2E"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<StackPanel>
<TextBlock FontFamily="Consolas" FontSize="12" FontWeight="Bold"
HorizontalAlignment="Right"
Text="{Binding PnL, StringFormat={}{0:+0.00;-0.00;0.00}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PnLCategory}" Value="loss">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding PnLCategory}" Value="open">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock FontFamily="Consolas" FontSize="10"
HorizontalAlignment="Right"
Text="{Binding PnLPercent, StringFormat={}{0:+0.0;-0.0;0.0}%}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PnLCategory}" Value="loss">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding PnLCategory}" Value="open">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</Border>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</Grid>
</Border>
</Grid>
</Grid>
</Grid>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class BotsManagerView : UserControl
{
public BotsManagerView()
{
InitializeComponent();
}
}
}
+438
View File
@@ -0,0 +1,438 @@
<UserControl x:Class="DesktopBot.Views.DashboardView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<Grid Background="{StaticResource BackgroundDarkBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- HEADER -->
<Grid Grid.Row="0" Margin="24,20,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="Dashboard" Style="{StaticResource SectionTitle}" Margin="0"/>
<Border Background="#1A1A2E" BorderBrush="{StaticResource AccentGreenBrush}" BorderThickness="1" CornerRadius="4" Padding="8,3" Margin="12,0,6,0" VerticalAlignment="Center">
<TextBlock Text="PAPER" Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="Bold"/>
</Border>
<Border Background="#1A1A2E" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="4" Padding="8,3" VerticalAlignment="Center">
<TextBlock Text="{Binding AccountStatus}" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold"/>
</Border>
<TextBlock Text="{Binding AccountNumber, StringFormat=' #{0}'}" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI Mono" FontSize="11" VerticalAlignment="Center" Margin="10,0,0,0"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="Caricamento..." Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="12" VerticalAlignment="Center" Margin="0,0,12,0" Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisConverter}}"/>
<Button Content="&#8635; Aggiorna" Command="{Binding RefreshCommand}" Style="{StaticResource OutlineButton}" Padding="14,7"/>
</StackPanel>
</Grid>
<!-- KPI CARDS -->
<UniformGrid Grid.Row="1" Columns="5" Margin="24,16,24,0">
<Border Style="{StaticResource Card}" Margin="0,0,8,0">
<StackPanel>
<TextBlock Text="EQUITY" Style="{StaticResource LabelSecondary}" Margin="0,0,0,6"/>
<TextBlock Text="{Binding Equity, StringFormat='${0:N2}'}" Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI" FontSize="20" FontWeight="Bold"/>
<TextBlock Text="Valore portafoglio" Style="{StaticResource LabelSecondary}" Margin="0,4,0,0"/>
</StackPanel>
</Border>
<Border Style="{StaticResource Card}" Margin="4,0">
<StackPanel>
<TextBlock Text="BUYING POWER" Style="{StaticResource LabelSecondary}" Margin="0,0,0,6"/>
<TextBlock Text="{Binding BuyingPower, StringFormat='${0:N2}'}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="20" FontWeight="Bold"/>
<TextBlock Text="Disponibile" Style="{StaticResource LabelSecondary}" Margin="0,4,0,0"/>
</StackPanel>
</Border>
<Border Style="{StaticResource Card}" Margin="4,0">
<StackPanel>
<TextBlock Text="P&amp;L GIORNALIERO" Style="{StaticResource LabelSecondary}" Margin="0,0,0,6"/>
<TextBlock Text="{Binding DailyPnL, StringFormat='{}{0:+$#,##0.00;-$#,##0.00;$0.00}'}" FontFamily="Segoe UI" FontSize="20" FontWeight="Bold">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsPnLPositive}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text="{Binding DailyPnLPercent, StringFormat='{}{0:+0.00;-0.00;0.00}%'}" Style="{StaticResource LabelSecondary}" Margin="0,4,0,0"/>
</StackPanel>
</Border>
<Border Style="{StaticResource Card}" Margin="4,0">
<StackPanel>
<TextBlock Text="POSIZIONI" Style="{StaticResource LabelSecondary}" Margin="0,0,0,6"/>
<TextBlock Text="{Binding OpenPositionsCount}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="20" FontWeight="Bold"/>
<TextBlock Text="Trade aperti" Style="{StaticResource LabelSecondary}" Margin="0,4,0,0"/>
</StackPanel>
</Border>
<Border Style="{StaticResource Card}" Margin="8,0,0,0">
<StackPanel>
<TextBlock Text="ORDINI APERTI" Style="{StaticResource LabelSecondary}" Margin="0,0,0,6"/>
<TextBlock Text="{Binding OpenOrdersCount}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="20" FontWeight="Bold"/>
<TextBlock Text="In attesa esecuzione" Style="{StaticResource LabelSecondary}" Margin="0,4,0,0"/>
</StackPanel>
</Border>
</UniformGrid>
<!-- STATO BOT -->
<Border Grid.Row="2" Margin="24,14,24,0" Background="{StaticResource BackgroundPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="8" Padding="16,12">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="STATO BOT" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Ellipse Width="8" Height="8" Margin="0,0,7,0" VerticalAlignment="Center">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="#888"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBotRunning}" Value="True">
<Setter Property="Fill" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<TextBlock Text="{Binding BotStatus}" FontFamily="Segoe UI" FontSize="13" FontWeight="SemiBold">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBotRunning}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Text="CONTO" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<TextBlock Text="{Binding AccountNumber, TargetNullValue='-'}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI Mono" FontSize="13"/>
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Text="STATO CONTO" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<TextBlock Text="{Binding AccountStatus, TargetNullValue='-'}" Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI" FontSize="13" FontWeight="SemiBold"/>
</StackPanel>
<StackPanel Grid.Column="3">
<TextBlock Text="VALUTA" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<TextBlock Text="{Binding Currency, TargetNullValue='-'}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="13"/>
</StackPanel>
</Grid>
</Border>
<!-- API COUNTER — Piano Basic gratuito: Market Data 200 req/min, Trading ~100 req/min -->
<Border Grid.Row="3" Margin="24,10,24,0" Background="{StaticResource BackgroundPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="8" Padding="16,10" DataContext="{Binding ApiCounter}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="0,0,8,0">
<TextBlock Text="MARKET DATA req/min" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding MarketDataRpm}" FontFamily="Segoe UI Mono" FontSize="16" FontWeight="Bold" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMarketDataNearLimit}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text=" / 200" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI Mono" FontSize="12" VerticalAlignment="Center"/>
</StackPanel>
<ProgressBar Value="{Binding MarketDataUsagePercent, Mode=OneWay}" Maximum="100" Height="4" Margin="0,5,8,0">
<ProgressBar.Style>
<Style TargetType="ProgressBar">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMarketDataNearLimit}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
</StackPanel>
<StackPanel Grid.Column="1" Margin="0,0,8,0">
<TextBlock Text="TRADING req/min" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding TradingRpm}" FontFamily="Segoe UI Mono" FontSize="16" FontWeight="Bold" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsTradingNearLimit}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text=" / 100" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI Mono" FontSize="12" VerticalAlignment="Center"/>
</StackPanel>
<ProgressBar Value="{Binding TradingUsagePercent, Mode=OneWay}" Maximum="100" Height="4" Margin="0,5,8,0">
<ProgressBar.Style>
<Style TargetType="ProgressBar">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsTradingNearLimit}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Text="TOT MARKET DATA" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<TextBlock Text="{Binding TotalMarketDataCalls}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI Mono" FontSize="16" FontWeight="Bold"/>
</StackPanel>
<StackPanel Grid.Column="3">
<TextBlock Text="TOT TRADING" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<TextBlock Text="{Binding TotalTradingCalls}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI Mono" FontSize="16" FontWeight="Bold"/>
</StackPanel>
<StackPanel Grid.Column="4">
<TextBlock Text="RALLENTATE" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<TextBlock Text="{Binding ThrottledCalls}" Foreground="{StaticResource AccentRedBrush}" FontFamily="Segoe UI Mono" FontSize="16" FontWeight="Bold"/>
</StackPanel>
</Grid>
</Border>
<!-- ERRORE -->
<Border Grid.Row="4" Margin="24,10,24,0" Background="#2A1515" BorderBrush="{StaticResource AccentRedBrush}" BorderThickness="1" CornerRadius="6" Padding="14,8" Visibility="{Binding HasError, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="{Binding ErrorMessage}" Foreground="{StaticResource AccentRedBrush}" FontFamily="Segoe UI" FontSize="12"/>
</Border>
<!-- POSIZIONI + ORDINI -->
<Grid Grid.Row="5" Margin="24,14,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="{StaticResource BackgroundPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="8" Padding="0">
<DockPanel>
<Border DockPanel.Dock="Top" BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1" Padding="14,10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="POSIZIONI APERTE" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold" VerticalAlignment="Center"/>
<TextBlock Text="{Binding OpenPositionsCount, StringFormat=' ({0})'}" Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold" VerticalAlignment="Center"/>
</StackPanel>
</Border>
<Grid DockPanel.Dock="Top" Background="{StaticResource BackgroundDarkBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="SIMBOLO" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="14,7,0,7"/>
<TextBlock Grid.Column="1" Text="QTY" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="0,7" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="2" Text="ENTRATA" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="0,7" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="3" Text="P&amp;L" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="0,7,14,7" HorizontalAlignment="Right"/>
</Grid>
<ItemsControl DockPanel.Dock="Top" ItemsSource="{Binding Positions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1" Padding="14,6">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Symbol}" Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI" FontWeight="SemiBold" FontSize="12" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Quantity}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="12" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding EntryPrice}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI Mono" FontSize="12" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBlock Grid.Column="3" Text="{Binding UnrealizedPnL}" FontFamily="Segoe UI Mono" FontSize="12" HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsPnLPositive}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</Border>
<Border Grid.Column="2" Background="{StaticResource BackgroundPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="8" Padding="0">
<DockPanel>
<Border DockPanel.Dock="Top" BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1" Padding="14,10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="ULTIMI ORDINI" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold" VerticalAlignment="Center"/>
<TextBlock Text="{Binding OpenOrdersCount, StringFormat=' ({0} aperti)'}" Foreground="{StaticResource AccentGreenBrush}" FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold" VerticalAlignment="Center"/>
</StackPanel>
</Border>
<Grid DockPanel.Dock="Top" Background="{StaticResource BackgroundDarkBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="LATO" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="14,7,0,7"/>
<TextBlock Grid.Column="1" Text="SIMBOLO" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="8,7"/>
<TextBlock Grid.Column="2" Text="QTY" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="0,7" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="3" Text="TIPO" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="0,7" HorizontalAlignment="Center"/>
<TextBlock Grid.Column="4" Text="STATO" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold" Padding="0,7" HorizontalAlignment="Center"/>
</Grid>
<ItemsControl DockPanel.Dock="Top" ItemsSource="{Binding Orders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1" Padding="0,4">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Background="{Binding SideBadgeColor}" CornerRadius="3" Padding="6,2" Margin="14,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center">
<TextBlock Text="{Binding Side}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Consolas" FontSize="10" FontWeight="Bold"/>
</Border>
<TextBlock Grid.Column="1" Text="{Binding Symbol}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="12" Padding="8,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding Qty}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="12" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBlock Grid.Column="3" Text="{Binding OrderType}" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="11" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Grid.Column="4" Text="{Binding Status}" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="11" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</Border>
</Grid>
<!-- LOG OPERAZIONI BOT -->
<Grid Grid.Row="6" Margin="24,14,24,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
<Ellipse Width="7" Height="7" Margin="0,0,8,0" VerticalAlignment="Center">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="#888"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBotRunning}" Value="True">
<Setter Property="Fill" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<TextBlock Text="Log Operazioni Bot" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="13" FontWeight="SemiBold" VerticalAlignment="Center"/>
<TextBlock Text="{Binding ActivityLog.Count, StringFormat=' ({0})'}" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="12" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="Aggiornamento automatico in tempo reale" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI" FontSize="11" VerticalAlignment="Center" Margin="0,0,10,0"/>
<Button Content="&#x1F4CB; Copia"
Command="{Binding CopyActivityLogCommand}"
Style="{StaticResource OutlineButton}"
Padding="10,4"
ToolTip="Copia tutti i log negli appunti"/>
</StackPanel>
</Grid>
<Border Grid.Row="1" Background="{StaticResource BackgroundPanelBrush}" BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" CornerRadius="8" Padding="0">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding ActivityLog}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1" Padding="16,7">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"/>
<ColumnDefinition Width="72"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Timestamp, StringFormat='HH:mm:ss dd/MM/yy'}" Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Consolas" FontSize="11" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="{Binding LevelBg}" CornerRadius="3" Padding="6,2" Margin="0,0,12,0" HorizontalAlignment="Left" VerticalAlignment="Center">
<TextBlock Text="{Binding Level}" Foreground="{Binding LevelColor}" FontFamily="Consolas" FontSize="10" FontWeight="Bold" VerticalAlignment="Center"/>
</Border>
<TextBlock Grid.Column="2" Text="{Binding Message}" Foreground="{StaticResource TextPrimaryBrush}" FontFamily="Segoe UI" FontSize="12" TextTrimming="CharacterEllipsis" VerticalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Border>
</Grid>
</Grid>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class DashboardView : UserControl
{
public DashboardView()
{
InitializeComponent();
}
}
}
+144
View File
@@ -0,0 +1,144 @@
<UserControl x:Class="DesktopBot.Views.LiveLogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:models="clr-namespace:DesktopBot.Models"
mc:Ignorable="d">
<Grid Background="{StaticResource BackgroundDarkBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- HEADER -->
<Grid Grid.Row="0" Margin="24,20,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="Live Log" Style="{StaticResource SectionTitle}" Margin="0"/>
<!-- Indicatore "In ascolto" -->
<Border Background="#1A00E676" BorderBrush="{StaticResource AccentGreenBrush}"
BorderThickness="1" CornerRadius="4" Padding="8,3" Margin="12,0,0,0"
VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<Ellipse Width="7" Height="7" Fill="{StaticResource AccentGreenBrush}"
Margin="0,0,6,0" VerticalAlignment="Center"/>
<TextBlock Text="IN ASCOLTO" Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI" FontSize="10" FontWeight="Bold" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<Button Content="&#x1F4CB; Copia"
Command="{Binding CopyLogsCommand}"
Style="{StaticResource OutlineButton}"
Padding="14,7"
Margin="0,0,8,0"
VerticalAlignment="Center"
ToolTip="Copia tutti i log negli appunti"/>
<Button Content="&#x1F5D1; Pulisci Log"
Command="{Binding ClearLogsCommand}"
Style="{StaticResource OutlineButton}"
Padding="14,7"
VerticalAlignment="Center"/>
</StackPanel>
</Grid>
<!-- Sottotitolo -->
<TextBlock Grid.Row="1" Margin="24,8,24,0"
Text="{Binding Logs.Count, StringFormat='Voci nel log: {0}'}"
Style="{StaticResource LabelSecondary}"/>
<!-- LOG LIST -->
<Border Grid.Row="2" Margin="24,14,24,20"
Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8" Padding="0">
<ListView x:Name="LogListView"
Style="{StaticResource LogListView}"
ItemsSource="{Binding Logs}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
BorderThickness="0"
Background="Transparent">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="16,6"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type models:BotLogEntry}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Timestamp, StringFormat='HH:mm:ss dd/MM'}"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Consolas" FontSize="11" VerticalAlignment="Center"/>
<Border Grid.Column="1" CornerRadius="3" Padding="6,2"
Margin="0,0,12,0" HorizontalAlignment="Left" VerticalAlignment="Center">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="#FF3A3A4A"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Level}" Value="Success">
<Setter Property="Background" Value="#1A00E676"/>
</DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Error">
<Setter Property="Background" Value="#1AFF1744"/>
</DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Warning">
<Setter Property="Background" Value="#1AFFC107"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="{Binding Level}"
FontFamily="Consolas" FontSize="10" FontWeight="Bold"
VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Level}" Value="Success">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Error">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Level}" Value="Warning">
<Setter Property="Foreground" Value="#FFFFC107"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
<TextBlock Grid.Column="2"
Text="{Binding Message}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Consolas" FontSize="12"
TextTrimming="CharacterEllipsis"
VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Border>
</Grid>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class LiveLogView : UserControl
{
public LiveLogView()
{
InitializeComponent();
}
}
}
+275
View File
@@ -0,0 +1,275 @@
<Window x:Class="DesktopBot.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:DesktopBot.ViewModels"
xmlns:views="clr-namespace:DesktopBot.Views"
xmlns:conv="clr-namespace:DesktopBot.Converters"
mc:Ignorable="d"
Title="Trading Bot"
Height="800" Width="1200"
MinHeight="600" MinWidth="900"
WindowStyle="SingleBorderWindow"
ResizeMode="CanResize"
Background="{StaticResource BackgroundDarkBrush}"
WindowStartupLocation="CenterScreen">
<Window.Resources>
<ResourceDictionary>
<!-- DataTemplate: mappa ogni ViewModel alla View corrispondente -->
<DataTemplate DataType="{x:Type vm:DashboardViewModel}">
<views:DashboardView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:BotsManagerViewModel}">
<views:BotsManagerView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:LiveLogViewModel}">
<views:LiveLogView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:WalletViewModel}">
<views:WalletView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SettingsViewModel}">
<views:SettingsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:BalanceViewModel}">
<views:BalanceView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:PositionsViewModel}">
<views:PositionsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:OrdersViewModel}">
<views:OrdersView/>
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<!-- Contenitore principale -->
<Grid>
<Grid.ColumnDefinitions>
<!-- Barra navigazione verticale sinistra -->
<ColumnDefinition Width="220"/>
<!-- Contenuto principale -->
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ========================== -->
<!-- BARRA NAVIGAZIONE SINISTRA -->
<!-- ========================== -->
<Border Grid.Column="0"
Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="0,0,1,0">
<DockPanel>
<!-- Logo / Equity nella parte alta -->
<Border DockPanel.Dock="Top"
Padding="20,20,20,16"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="0,0,0,1">
<StackPanel>
<TextBlock Text="Equity"
Style="{StaticResource LabelSecondary}"
FontFamily="Segoe UI"
Margin="0,0,0,4"/>
<TextBlock Text="{Binding DashboardVM.Equity, StringFormat='${0:N2}'}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI"
FontSize="22"
FontWeight="Bold"/>
<!-- Ping Alpaca -->
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<Ellipse Width="8" Height="8" VerticalAlignment="Center" Margin="0,0,6,0"
Fill="{Binding PingVM.StatusColor, Mode=OneWay}"/>
<TextBlock Style="{StaticResource LabelSecondary}" FontSize="10"
VerticalAlignment="Center">
<Run Text="Alpaca "/>
<Run Text="{Binding PingVM.StatusText, Mode=OneWay, FallbackValue='---'}"
Foreground="{Binding PingVM.StatusColor, Mode=OneWay}"/>
</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<!-- Menu di navigazione verticale -->
<StackPanel DockPanel.Dock="Top" Margin="0,16,0,0">
<!-- Dashboard -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="Dashboard">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="Dashboard">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="⬛" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Dashboard" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<!-- Bot -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="Bot">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="Bot">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="🤖" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Bot" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<!-- Live Log -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="LiveLog">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="LiveLog">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="📋" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Log" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<!-- Wallet / Positions -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="Wallet">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="Wallet">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="💼" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Wallet" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<!-- Balance -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="Balance">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="Balance">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#x1F4B0;" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Balance" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<!-- Positions -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="Positions">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="Positions">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#x1F4C8;" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Posizioni" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<!-- Orders -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="Orders">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="Orders">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#x1F4CB;" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Ordini" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<!-- Separatore -->
<Separator Background="{StaticResource BorderBrush}" Margin="16,8"/>
<!-- Impostazioni -->
<Button Command="{Binding NavigateCommand}"
CommandParameter="Settings">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource NavItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedTab}" Value="Settings">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<StackPanel Orientation="Horizontal">
<TextBlock Text="🔑" FontSize="14" Margin="0,0,12,0" VerticalAlignment="Center"/>
<TextBlock Text="Impostazioni" FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Button>
</StackPanel>
<!-- Spacer -->
<Grid DockPanel.Dock="Top"/>
</DockPanel>
</Border>
<!-- ========================== -->
<!-- AREA CONTENUTO PRINCIPALE -->
<!-- ========================== -->
<ContentControl x:Name="MainContent"
Grid.Column="1"
Content="{Binding CurrentViewModel}"
Margin="0"/>
</Grid>
</Window>
+17
View File
@@ -0,0 +1,17 @@
using System.Windows;
using DesktopBot.ViewModels;
namespace DesktopBot.Views
{
/// <summary>
/// MainView - Finestra principale con navigazione verticale dark mode
/// </summary>
public partial class MainView : Window
{
public MainView()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
}
+199
View File
@@ -0,0 +1,199 @@
<UserControl x:Class="DesktopBot.Views.OrdersView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="ColH" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Padding" Value="8,8"/>
</Style>
<Style x:Key="Cell" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</UserControl.Resources>
<Grid Background="{StaticResource BackgroundDarkBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Header -->
<Grid Grid.Row="0" Margin="24,20,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Ordini" Style="{StaticResource SectionTitle}" Margin="0"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="Caricamento..." Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="12" VerticalAlignment="Center" Margin="0,0,12,0"
Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisConverter}}"/>
<Button Content="&#8635; Aggiorna" Command="{Binding RefreshCommand}"
Style="{StaticResource OutlineButton}" Padding="14,7"/>
</StackPanel>
</Grid>
<TextBlock Grid.Row="1" Margin="24,8,24,0"
Text="{Binding Orders.Count, StringFormat='Ordini totali: {0}'}"
Style="{StaticResource LabelSecondary}"/>
<!-- Errore -->
<Border Grid.Row="2" Margin="24,10,24,0"
Background="#2A1515" BorderBrush="{StaticResource AccentRedBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,8"
Visibility="{Binding HasError, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="{Binding ErrorMessage}" Foreground="{StaticResource AccentRedBrush}"
FontFamily="Segoe UI" FontSize="12"/>
</Border>
<!-- Header colonne -->
<Grid Grid.Row="3" Margin="24,14,24,0" Background="{StaticResource BackgroundPanelBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="65"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="145"/>
<ColumnDefinition Width="145"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Asset" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="1" Text="Tipo" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="2" Text="Side" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="3" Text="Qty" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="4" Text="Filled" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="5" Text="Avg Fill" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="6" Text="Limit" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="7" Text="Stato" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="8" Text="Inviato" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="9" Text="Eseguito" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="10" Text="" Style="{StaticResource ColH}"/>
</Grid>
<!-- Righe ordini -->
<ScrollViewer Grid.Row="4" Margin="24,0,24,20" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Orders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1A1A2E"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="65"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="145"/>
<ColumnDefinition Width="145"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Symbol}"
FontWeight="Bold" FontFamily="Segoe UI" FontSize="13"
Foreground="{StaticResource TextPrimaryBrush}" Padding="8,5"/>
<TextBlock Grid.Column="1" Text="{Binding OrderType}" Style="{StaticResource Cell}"
Foreground="{StaticResource TextSecondaryBrush}"/>
<Border Grid.Column="2" CornerRadius="3" Margin="4,7" Padding="6,2"
Background="{Binding SideBadgeColor}" VerticalAlignment="Center">
<TextBlock Text="{Binding Side}" FontFamily="Segoe UI" FontSize="10" FontWeight="Bold"
HorizontalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Side}" Value="BUY">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
<TextBlock Grid.Column="3" Text="{Binding Qty}" Style="{StaticResource Cell}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="4" Text="{Binding FilledQty}" Style="{StaticResource Cell}" HorizontalAlignment="Right" Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBlock Grid.Column="5" Text="{Binding AvgFillPrice}" Style="{StaticResource Cell}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="6" Text="{Binding LimitPrice}" Style="{StaticResource Cell}" HorizontalAlignment="Right" Foreground="{StaticResource TextSecondaryBrush}"/>
<!-- Badge stato -->
<Border Grid.Column="7" CornerRadius="3" Margin="4,7" Padding="6,2" VerticalAlignment="Center">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="#2A2A3A"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOpen}" Value="True">
<Setter Property="Background" Value="#1A2A3A"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="{Binding Status}" FontFamily="Segoe UI" FontSize="10" FontWeight="SemiBold"
HorizontalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOpen}" Value="True">
<Setter Property="Foreground" Value="#5BB8FF"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
<TextBlock Grid.Column="8" Text="{Binding SubmittedAt}" Style="{StaticResource Cell}"
Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI Mono" FontSize="11"/>
<TextBlock Grid.Column="9" Text="{Binding FilledAt}" Style="{StaticResource Cell}"
Foreground="{StaticResource TextSecondaryBrush}" FontFamily="Segoe UI Mono" FontSize="11"/>
<Button Grid.Column="10" Content="Cancella"
Command="{Binding DataContext.CancelOrderCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding OrderId}"
Style="{StaticResource DangerButton}" Padding="8,4" Margin="4"
Visibility="{Binding IsOpen, Converter={StaticResource BoolToVisConverter}}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Style>
<Style TargetType="ItemsControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Orders.Count}" Value="0">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="Nessun ordine trovato."
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="13"
HorizontalAlignment="Center" Margin="0,50"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.Style>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
+8
View File
@@ -0,0 +1,8 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class OrdersView : UserControl
{
public OrdersView() { InitializeComponent(); }
}
}
+182
View File
@@ -0,0 +1,182 @@
<UserControl x:Class="DesktopBot.Views.PositionsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<UserControl.Resources>
<Style x:Key="ColH" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Padding" Value="8,8"/>
</Style>
<Style x:Key="Cell" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="PnLCell" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="8,6"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsProfit}" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid Background="{StaticResource BackgroundDarkBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Header -->
<Grid Grid.Row="0" Margin="24,20,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Posizioni" Style="{StaticResource SectionTitle}" Margin="0"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="Caricamento..." Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="12" VerticalAlignment="Center" Margin="0,0,12,0"
Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisConverter}}"/>
<Button Content="Chiudi Tutte" Command="{Binding CloseAllCommand}"
Style="{StaticResource DangerButton}" Padding="12,7" Margin="0,0,8,0"/>
<Button Content="&#8635; Aggiorna" Command="{Binding RefreshCommand}"
Style="{StaticResource OutlineButton}" Padding="14,7"/>
</StackPanel>
</Grid>
<TextBlock Grid.Row="1" Margin="24,8,24,0"
Text="{Binding Positions.Count, StringFormat='Posizioni aperte: {0}'}"
Style="{StaticResource LabelSecondary}"/>
<!-- Errore -->
<Border Grid.Row="2" Margin="24,10,24,0"
Background="#2A1515" BorderBrush="{StaticResource AccentRedBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,8"
Visibility="{Binding HasError, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="{Binding ErrorMessage}" Foreground="{StaticResource AccentRedBrush}"
FontFamily="Segoe UI" FontSize="12"/>
</Border>
<!-- Header colonne -->
<Grid Grid.Row="3" Margin="24,14,24,0" Background="{StaticResource BackgroundPanelBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="65"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Asset" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="1" Text="Side" Style="{StaticResource ColH}"/>
<TextBlock Grid.Column="2" Text="Qty" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="3" Text="Avg Entry" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="4" Text="Prezzo Att." Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="5" Text="Market Value" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="6" Text="P&amp;L ($)" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="7" Text="P&amp;L (%)" Style="{StaticResource ColH}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="8" Text="Azioni" Style="{StaticResource ColH}" HorizontalAlignment="Center"/>
</Grid>
<!-- Righe posizioni -->
<ScrollViewer Grid.Row="4" Margin="24,0,24,20" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Positions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource BorderBrush}" BorderThickness="0,0,0,1">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1A1A2E"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="65"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Symbol}"
FontWeight="Bold" FontFamily="Segoe UI" FontSize="13"
Foreground="{StaticResource TextPrimaryBrush}" Padding="8,5"/>
<Border Grid.Column="1" CornerRadius="3" Margin="4,7,4,7" Padding="6,2"
Background="{Binding SideBadgeColor}" VerticalAlignment="Center">
<TextBlock Text="{Binding Side}" FontFamily="Segoe UI" FontSize="10" FontWeight="Bold"
HorizontalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Side}" Value="LONG">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
<TextBlock Grid.Column="2" Text="{Binding Quantity}" Style="{StaticResource Cell}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="3" Text="{Binding EntryPrice, StringFormat={}{0:N2}}" Style="{StaticResource Cell}" HorizontalAlignment="Right" Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBlock Grid.Column="4" Text="{Binding CurrentPrice, StringFormat={}{0:N2}}" Style="{StaticResource Cell}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="5" Text="{Binding MarketValue, StringFormat={}{0:N2}}" Style="{StaticResource Cell}" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="6"
Style="{StaticResource PnLCell}"
Text="{Binding UnrealizedPnL, StringFormat={}{0:N2}}"/>
<TextBlock Grid.Column="7"
Style="{StaticResource PnLCell}"
Text="{Binding UnrealizedPnLPercent, StringFormat={}{0:N2}%}"/>
<Button Grid.Column="8" Content="Chiudi"
Command="{Binding DataContext.ClosePositionCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding Symbol}"
Style="{StaticResource DangerButton}" Padding="8,4" Margin="4"
HorizontalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Style>
<Style TargetType="ItemsControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Positions.Count}" Value="0">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="Nessuna posizione aperta."
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="13"
HorizontalAlignment="Center" Margin="0,50"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.Style>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
+8
View File
@@ -0,0 +1,8 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class PositionsView : UserControl
{
public PositionsView() { InitializeComponent(); }
}
}
+184
View File
@@ -0,0 +1,184 @@
<UserControl x:Class="DesktopBot.Views.PriceChartView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="600" d:DesignWidth="900"
Background="#1E1E1E">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Header con prezzo corrente -->
<StackPanel Grid.Row="0" Margin="0,0,0,20">
<TextBlock Text="GRAFICO PREZZI REAL-TIME"
FontSize="24" FontWeight="Bold"
Foreground="#E0E0E0" Margin="0,0,0,10"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Simbolo e prezzo -->
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="{Binding Symbol}"
FontSize="28" FontWeight="Bold"
Foreground="#FFFFFF" Margin="0,0,15,0"/>
<TextBlock Text="{Binding CurrentPrice, StringFormat=C2}"
FontSize="28" FontWeight="Bold"
Foreground="#00E676"/>
</StackPanel>
<!-- Variazione prezzo -->
<StackPanel Grid.Column="1" Orientation="Horizontal"
HorizontalAlignment="Left" Margin="20,0,0,0">
<TextBlock Text="{Binding PriceChangeIcon}"
FontSize="20"
Foreground="{Binding PriceChangeColor}"/>
<TextBlock Text="{Binding PriceChange, StringFormat=F2}"
FontSize="18"
Foreground="{Binding PriceChangeColor}"
Margin="5,0,10,0"/>
<TextBlock Text="{Binding PriceChangePercent, StringFormat=({0:F2}%)}"
FontSize="18"
Foreground="{Binding PriceChangeColor}"/>
</StackPanel>
<!-- Controlli -->
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right">
<ComboBox Width="120" Margin="0,0,10,0"
Background="#2D2D30" Foreground="#E0E0E0"
BorderBrush="#3E3E42"
SelectedIndex="0">
<ComboBoxItem Content="1 Minuto"/>
<ComboBoxItem Content="5 Minuti"/>
<ComboBoxItem Content="1 Ora"/>
</ComboBox>
<Button Content="▶ START"
Width="100" Height="35"
Background="#00E676" Foreground="#000000"
FontWeight="Bold"
Command="{Binding StartStreamCommand}"
Margin="0,0,5,0"/>
<Button Content="■ STOP"
Width="100" Height="35"
Background="#FF5252" Foreground="#FFFFFF"
FontWeight="Bold"
Command="{Binding StopStreamCommand}"/>
</StackPanel>
</Grid>
</StackPanel>
<!-- Status bar -->
<Border Grid.Row="1"
Background="#252526"
Padding="10,8"
CornerRadius="4"
Margin="0,0,0,15">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse Grid.Column="0"
Width="12" Height="12"
Margin="0,0,10,0"
VerticalAlignment="Center">
<Ellipse.Fill>
<SolidColorBrush Color="{Binding IsStreaming, Converter={StaticResource BoolToStreamColorConverter}}"/>
</Ellipse.Fill>
</Ellipse>
<TextBlock Grid.Column="1"
Text="{Binding StatusMessage}"
FontSize="13"
Foreground="#B0B0B0"
VerticalAlignment="Center"/>
</Grid>
</Border>
<!-- Area grafico (placeholder - qui si integrerebbe LiveCharts/OxyPlot) -->
<Border Grid.Row="2"
Background="#252526"
BorderBrush="#3E3E42"
BorderThickness="1"
CornerRadius="8"
Padding="20">
<Grid>
<!-- Griglia con dati tabulari temporanea -->
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding PriceData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Timestamp, StringFormat=dd/MM/yyyy HH:mm:ss}"
Foreground="#B0B0B0" FontSize="11"/>
<TextBlock Grid.Column="1"
Text="{Binding Price, StringFormat=C2}"
Foreground="#00E676" FontSize="12" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- Messaggio per integrare libreria charting -->
<Border Background="#1E1E1E"
BorderBrush="#FFD700"
BorderThickness="2"
CornerRadius="8"
Padding="30"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Opacity="0.95">
<StackPanel>
<TextBlock Text="📊 GRAFICO VISUALE"
FontSize="20" FontWeight="Bold"
Foreground="#FFD700"
HorizontalAlignment="Center"
Margin="0,0,0,15"/>
<TextBlock TextWrapping="Wrap"
Foreground="#E0E0E0"
TextAlignment="Center"
MaxWidth="400">
Per visualizzare il grafico dei prezzi in tempo reale,
<LineBreak/>
installare una libreria di charting come:
<LineBreak/><LineBreak/>
<Bold>• LiveCharts2</Bold> (NuGet: LiveChartsCore.SkiaSharpView.WPF)
<LineBreak/>
<Bold>• OxyPlot</Bold> (NuGet: OxyPlot.Wpf)
<LineBreak/><LineBreak/>
I dati sono già disponibili in <Bold>PriceData</Bold>.
</TextBlock>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Footer info -->
<TextBlock Grid.Row="3"
Text="Dati forniti da Alpaca Markets (feed IEX) • Aggiornamento ogni 5 secondi"
FontSize="11"
Foreground="#707070"
HorizontalAlignment="Center"
Margin="0,15,0,0"/>
</Grid>
</UserControl>
+15
View File
@@ -0,0 +1,15 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
/// <summary>
/// Interaction logic for PriceChartView.xaml
/// </summary>
public partial class PriceChartView : UserControl
{
public PriceChartView()
{
InitializeComponent();
}
}
}
+426
View File
@@ -0,0 +1,426 @@
<UserControl x:Class="DesktopBot.Views.SettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{StaticResource BackgroundDarkBrush}">
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="32">
<StackPanel MaxWidth="540" HorizontalAlignment="Left">
<!-- Titolo sezione -->
<TextBlock Text="Impostazioni API"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI"
FontSize="22" FontWeight="SemiBold"
Margin="0,0,0,4"/>
<TextBlock Text="Configura le credenziali per la connessione ad Alpaca Markets"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="13"
Margin="0,0,0,32"/>
<!-- Card credenziali -->
<Border Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8"
Padding="24" Margin="0,0,0,16">
<StackPanel>
<TextBlock Text="Credenziali Alpaca"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="15" FontWeight="SemiBold"
Margin="0,0,0,20"/>
<!-- API Key -->
<TextBlock Text="API KEY"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,6"/>
<TextBox x:Name="ApiKeyBox"
Text="{Binding ApiKey, UpdateSourceTrigger=PropertyChanged}"
Background="#1A1A2E"
Foreground="{StaticResource TextPrimaryBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1"
FontFamily="Consolas" FontSize="13"
Padding="10,8"
CaretBrush="White"
Margin="0,0,0,16"/>
<!-- API Secret -->
<TextBlock Text="API SECRET"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,6"/>
<PasswordBox x:Name="ApiSecretBox"
Background="#1A1A2E"
Foreground="{StaticResource TextPrimaryBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1"
FontFamily="Consolas" FontSize="13"
Padding="10,8"
CaretBrush="White"
Margin="0,0,0,24"
PasswordChanged="ApiSecretBox_PasswordChanged"/>
<!-- Modalità Paper / Live -->
<TextBlock Text="MODALITÀ DI TRADING"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,10"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,24">
<RadioButton x:Name="PaperRadio"
Content="Paper Trading (simulazione)"
IsChecked="{Binding IsPaper}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="13"
Margin="0,0,24,0">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
<RadioButton Content="Live Trading ⚠ FONDI REALI"
IsChecked="{Binding IsPaper, Converter={StaticResource InverseBoolConverter}}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="13">
<RadioButton.Style>
<Style TargetType="RadioButton">
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
</StackPanel>
<!-- Pulsanti azione -->
<StackPanel Orientation="Horizontal">
<Button Content="💾 Salva Credenziali"
Command="{Binding SaveCommand}"
Style="{StaticResource PrimaryButton}"
Padding="20,10"
Margin="0,0,12,0"/>
<Button Content="⚡ Test Connessione"
Command="{Binding TestConnectionCommand}"
Style="{StaticResource OutlineButton}"
Padding="20,10"
Margin="0,0,12,0"/>
<Button Content="🗑 Elimina"
Command="{Binding DeleteCredentialsCommand}"
Style="{StaticResource DangerButton}"
Padding="16,10"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Card stato connessione -->
<Border Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8"
Padding="20,16">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<!-- Indicatore stato -->
<Ellipse Width="10" Height="10" Margin="0,0,10,0">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="#FF5555"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Fill" Value="{StaticResource AccentGreenBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsConnecting}" Value="True">
<Setter Property="Fill" Value="#FFD700"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<TextBlock Text="{Binding StatusMessage}"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="13"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
<!-- Info sicurezza -->
<Border Margin="0,16,0,0" Padding="16,12"
Background="#0D1B2A"
BorderBrush="#1E3A5F"
BorderThickness="1" CornerRadius="6">
<StackPanel Orientation="Horizontal">
<TextBlock Text="🔒" FontSize="14" Margin="0,0,10,0" VerticalAlignment="Center"/>
<TextBlock TextWrapping="Wrap"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="12">
<Run Text="Le credenziali sono cifrate con Windows DPAPI e salvate localmente in "/>
<Run Text="%AppData%\TradingBot\" FontFamily="Consolas" FontWeight="SemiBold"/>
<Run Text=". Non vengono mai trasmesse a servizi di terze parti."/>
</TextBlock>
</StackPanel>
</Border>
<!-- Card limiti logging -->
<Border Margin="0,24,0,0"
Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8"
Padding="24">
<StackPanel>
<TextBlock Text="Configurazione Log"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="15" FontWeight="SemiBold"
Margin="0,0,0,4"/>
<TextBlock Text="Configura i limiti di conservazione dei dati storici e log"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11"
Margin="0,0,0,20"/>
<!-- Max Bot Log Entries -->
<Grid Margin="0,0,0,16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="LOG BOT"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,4"/>
<TextBlock Text="Elementi massimi nel log del bot"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="10"
Opacity="0.8"/>
</StackPanel>
<Slider Grid.Column="1"
Minimum="500" Maximum="10000" SmallChange="100" LargeChange="500"
Value="{Binding LoggingSettings.MaxBotLogEntries, UpdateSourceTrigger=PropertyChanged}"
Margin="16,0,16,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2"
Text="{Binding LoggingSettings.MaxBotLogEntries}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI Mono" FontSize="13" FontWeight="SemiBold"
TextAlignment="Right" VerticalAlignment="Center"/>
</Grid>
<!-- Max Trade History Entries -->
<Grid Margin="0,0,0,16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="STORICO TRADE"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,4"/>
<TextBlock Text="Elementi massimi nello storico trade"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="10"
Opacity="0.8"/>
</StackPanel>
<Slider Grid.Column="1"
Minimum="500" Maximum="5000" SmallChange="100" LargeChange="500"
Value="{Binding LoggingSettings.MaxTradeHistoryEntries, UpdateSourceTrigger=PropertyChanged}"
Margin="16,0,16,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2"
Text="{Binding LoggingSettings.MaxTradeHistoryEntries}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI Mono" FontSize="13" FontWeight="SemiBold"
TextAlignment="Right" VerticalAlignment="Center"/>
</Grid>
<!-- Max Activity Log Entries -->
<Grid Margin="0,0,0,16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="LOG ATTIVITÀ"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,4"/>
<TextBlock Text="Elementi massimi nel log attività dashboard"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="10"
Opacity="0.8"/>
</StackPanel>
<Slider Grid.Column="1"
Minimum="1000" Maximum="10000" SmallChange="100" LargeChange="500"
Value="{Binding LoggingSettings.MaxActivityLogEntries, UpdateSourceTrigger=PropertyChanged}"
Margin="16,0,16,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2"
Text="{Binding LoggingSettings.MaxActivityLogEntries}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI Mono" FontSize="13" FontWeight="SemiBold"
TextAlignment="Right" VerticalAlignment="Center"/>
</Grid>
<!-- Max Live Log Entries -->
<Grid Margin="0,0,0,16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="LOG LIVE GLOBALE"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,4"/>
<TextBlock Text="Elementi massimi nel log live globale"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="10"
Opacity="0.8"/>
</StackPanel>
<Slider Grid.Column="1"
Minimum="2000" Maximum="20000" SmallChange="100" LargeChange="1000"
Value="{Binding LoggingSettings.MaxLiveLogEntries, UpdateSourceTrigger=PropertyChanged}"
Margin="16,0,16,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2"
Text="{Binding LoggingSettings.MaxLiveLogEntries}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI Mono" FontSize="13" FontWeight="SemiBold"
TextAlignment="Right" VerticalAlignment="Center"/>
</Grid>
<!-- Max Price Data Points -->
<Grid Margin="0,0,0,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="DATI GRAFICO"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
Margin="0,0,0,4"/>
<TextBlock Text="Punti dati massimi nel grafico prezzi"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="10"
Opacity="0.8"/>
</StackPanel>
<Slider Grid.Column="1"
Minimum="500" Maximum="10000" SmallChange="100" LargeChange="500"
Value="{Binding LoggingSettings.MaxPriceDataPoints, UpdateSourceTrigger=PropertyChanged}"
Margin="16,0,16,0" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2"
Text="{Binding LoggingSettings.MaxPriceDataPoints}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI Mono" FontSize="13" FontWeight="SemiBold"
TextAlignment="Right" VerticalAlignment="Center"/>
</Grid>
<!-- Pulsanti azione logging -->
<StackPanel Orientation="Horizontal">
<Button Content="💾 Salva Configurazione Log"
Command="{Binding SaveLoggingCommand}"
Style="{StaticResource PrimaryButton}"
Padding="20,10"
Margin="0,0,12,0"/>
<Button Content="↺ Ripristina Default"
Command="{Binding ResetLoggingCommand}"
Style="{StaticResource OutlineButton}"
Padding="20,10"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Informazioni applicazione -->
<Border Margin="0,24,0,0"
Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8"
Padding="24">
<StackPanel>
<TextBlock Text="Informazioni"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="15" FontWeight="SemiBold"
Margin="0,0,0,20"/>
<!-- Autore -->
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="AUTORE"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Author}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="13"/>
</Grid>
<!-- Versione -->
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="VERSIONE"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding AppVersion}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI Mono" FontSize="13" FontWeight="SemiBold"/>
</Grid>
<!-- Data ultima build -->
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="ULTIMA BUILD"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding BuildDate}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI Mono" FontSize="13"/>
</Grid>
<!-- Framework -->
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="FRAMEWORK"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="11" FontWeight="SemiBold"
VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Framework}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="13"/>
</Grid>
<!-- Descrizione -->
<Separator Background="{StaticResource BorderBrush}" Margin="0,10,0,14"/>
<TextBlock Text="{Binding Description}"
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="12"
TextWrapping="Wrap" LineHeight="20"/>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</UserControl>
+35
View File
@@ -0,0 +1,35 @@
using System.Windows.Controls;
using DesktopBot.ViewModels;
namespace DesktopBot.Views
{
/// <summary>
/// Code-behind per SettingsView.
/// Gestisce il PasswordBox (non bindabile in WPF) passando il valore al ViewModel.
/// </summary>
public partial class SettingsView : UserControl
{
private SettingsViewModel ViewModel => DataContext as SettingsViewModel;
public SettingsView()
{
InitializeComponent();
// Quando il DataContext cambia, pre-popola il PasswordBox
DataContextChanged += (s, e) =>
{
if (ViewModel?.ApiSecret != null)
ApiSecretBox.Password = ViewModel.ApiSecret;
};
}
/// <summary>
/// Aggiorna il ViewModel ogni volta che l'utente modifica il PasswordBox
/// </summary>
private void ApiSecretBox_PasswordChanged(object sender, System.Windows.RoutedEventArgs e)
{
if (ViewModel != null)
ViewModel.ApiSecret = ApiSecretBox.Password;
}
}
}
+176
View File
@@ -0,0 +1,176 @@
<UserControl x:Class="DesktopBot.Views.WalletView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource BackgroundDarkBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- HEADER -->
<Grid Grid.Row="0" Margin="24,20,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Wallet &amp; Posizioni"
Style="{StaticResource SectionTitle}" Margin="0"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="Caricamento..."
Foreground="{StaticResource TextSecondaryBrush}"
FontFamily="Segoe UI" FontSize="12" VerticalAlignment="Center"
Margin="0,0,12,0"
Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisConverter}}"/>
<Button Content="Chiudi Tutto"
Command="{Binding CloseAllCommand}"
Style="{StaticResource DangerButton}"
Padding="12,7" Margin="0,0,8,0"
VerticalAlignment="Center"/>
<Button Content="&#8635; Aggiorna"
Command="{Binding RefreshCommand}"
Style="{StaticResource OutlineButton}"
Padding="14,7"
VerticalAlignment="Center"/>
</StackPanel>
</Grid>
<!-- Sottotitolo -->
<TextBlock Grid.Row="1" Margin="24,8,24,0"
Text="{Binding Positions.Count, StringFormat='Posizioni aperte: {0}'}"
Style="{StaticResource LabelSecondary}"/>
<!-- Errore -->
<Border Grid.Row="2" Margin="24,10,24,0"
Background="#2A1515" BorderBrush="{StaticResource AccentRedBrush}"
BorderThickness="1" CornerRadius="6" Padding="14,8"
Visibility="{Binding HasError, Converter={StaticResource BoolToVisConverter}}">
<TextBlock Text="{Binding ErrorMessage}"
Foreground="{StaticResource AccentRedBrush}"
FontFamily="Segoe UI" FontSize="12"/>
</Border>
<!-- Equity Summary -->
<Border Grid.Row="3" Margin="24,14,24,0"
Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8" Padding="20,14">
<StackPanel Orientation="Horizontal">
<StackPanel Margin="0,0,48,0">
<TextBlock Text="EQUITY TOTALE" Style="{StaticResource LabelSecondary}" Margin="0,0,0,4"/>
<TextBlock Text="{Binding Equity, StringFormat='${0:N2}'}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI" FontSize="28" FontWeight="Bold"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Tabella Posizioni -->
<Border Grid.Row="4" Margin="24,14,24,20"
Background="{StaticResource BackgroundPanelBrush}"
BorderBrush="{StaticResource BorderBrush}"
BorderThickness="1" CornerRadius="8" Padding="0">
<DockPanel>
<!-- Header colonne -->
<Grid DockPanel.Dock="Top"
Background="{StaticResource BackgroundDarkBrush}"
Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="SIMBOLO" Style="{StaticResource LabelSecondary}" Padding="20,12"/>
<TextBlock Grid.Column="1" Text="QUANTIT&#xC0;" Style="{StaticResource LabelSecondary}" Padding="0,12"/>
<TextBlock Grid.Column="2" Text="PREZZO ENTRATA" Style="{StaticResource LabelSecondary}" Padding="0,12"/>
<TextBlock Grid.Column="3" Text="PREZZO ATTUALE" Style="{StaticResource LabelSecondary}" Padding="0,12"/>
<TextBlock Grid.Column="4" Text="P&amp;L NON REALIZ." Style="{StaticResource LabelSecondary}" Padding="0,12"/>
</Grid>
<!-- Lista Posizioni -->
<ListView DockPanel.Dock="Top"
ItemsSource="{Binding Positions}"
Background="Transparent"
BorderThickness="0">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource NavActiveBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="120"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Symbol}"
Foreground="{StaticResource AccentGreenBrush}"
FontFamily="Segoe UI" FontWeight="SemiBold" FontSize="14"
Padding="20,10" VerticalAlignment="Center"/>
<TextBlock Grid.Column="1" Text="{Binding Quantity}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Text="{Binding EntryPrice, StringFormat='${0:N2}'}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
<TextBlock Grid.Column="3" Text="{Binding CurrentPrice, StringFormat='${0:N2}'}"
Foreground="{StaticResource TextPrimaryBrush}"
FontFamily="Segoe UI" FontSize="13" VerticalAlignment="Center"/>
<TextBlock Grid.Column="4" Text="{Binding UnrealizedPnL, StringFormat='${0:N2}'}"
FontFamily="Segoe UI" FontWeight="SemiBold" FontSize="13"
VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource AccentGreenBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsProfit}" Value="False">
<Setter Property="Foreground" Value="{StaticResource AccentRedBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!-- Placeholder vuoto -->
<TextBlock DockPanel.Dock="Top"
Text="Nessuna posizione aperta"
HorizontalAlignment="Center" Margin="0,40">
<TextBlock.Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource LabelSecondary}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Positions.Count}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DockPanel>
</Border>
</Grid>
</UserControl>
+12
View File
@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace DesktopBot.Views
{
public partial class WalletView : UserControl
{
public WalletView()
{
InitializeComponent();
}
}
}