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
+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>