C# :: Aufgabe #185 :: Lösung #1

3 Lösungen Lösungen öffentlich
#185

Wetteinsatzstrategien: statisch, martingal, reverse-martingal oder Fibonacci

Fortgeschrittener - C# von hollst - 18.07.2017 um 09:49 Uhr
Bei zweiwertigen Wettspielen wie bspw. Münzwerfen (Kopf/Zahl), Roulette (Rot/Blau) oder Würfeln (gerade Zahl/ungerade Zahl) gibt es verschiedene Strategien zum Setzen des Einsatzes, um eingefahrenen Verlust so schnell wie möglich wieder zurückzuholen. Neben der statischen Strategie, d. h. man setzt in jeder Runde immer auf das gleiche Ereignis, sind die bekanntesten Strategien die martingale, die reverse-martingale und die Fibonacci-Strategie.

Die martingale Strategie sollte in der Praxis immer zu einem Gewinn führen, allerdings bräuchte man dafür unbegrenzte Ressourcen in der Hinterhand und einen Gegener (die Bank), der sich darauf einlässt. Die Strategie geht wie folgt: Hat man in einer Runde verloren, so setzt man in der Folgerunde den doppelten Einsatz. Die Hoffnung ist, dass man keine zu lang anhaltende Pechstähne hat und irgendwann auch einmal gewinnt. In diesem Falle hat man unter dem Strich genau seinen Starteinsatz gewonnen. Allerdings sind eiserne Nerven notwendig. Gehen wir einmal davon aus, dass wir mit dem Starteinsatz von einem EURO begonnen haben und zehnmal hintereinander verloren (1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 + 256 + 512 = 1.023), also bereits bei einem Spielstand von -1.023 EURO stehen. Für den elften Versuch müssten wir 1.024 EURO setzen mit der Perspektive, bei einem Gewinn unter dem Strich genau einen einzigen EURO gewonnen zu haben oder bei Verlust auf dann -2.047 EURO zu sitzen. Mindestens an dieser Stelle würde die Bank das Spiel sicher auch abbrechen.

Bei der reverse-martingalen Strategie geht man ganau anders herum vor: Bei einem Verlust setzt man immer wieder den gleichen Startbetrag (sagen wir wieder einen EURO). Bei einem Gewinn hofft man, dass dies der Beginn einer kleinen Glückssträhne ist und wir verdoppeln für die nächste Wettrunde den Einsatz. Die Länge dieser Strähne muss allerdings zuvor festgelegt worden sein, nehmen wir bspw. fünf an. Ist sie eingetroffen, dann beginnen wir wieder mit dem Starteinsatz und streichen die hier z. B. insgesamt gewonnenen 31 EURO ein. Bei der reverse-martingalen Strategie führt ein Rundenverlust immer nur zum Verlust des Starteinsatzes (ein EURO) u. z. auch dann nur, wenn die angestrebte Gewinnserie z. B. erst mit der letzten Wette (fünften) zerstört worden ist.

Bei der Fibonacci-Strategie folgt man bzgl. des Wetteinsatzes der Fibonaccireihe (1, 1, 2, 3, 5, 8, 13, 21, 34 …). Man startet bei 1 und im Falle eines oder mehrerer Verluste geht man jeweils einen Schritt weiter in der Folge. Der Wetteinsatz ist dann das Produkt des Starteinsatzes (ein EURO) mit der entsprechenden Fibonaccizahl. Im Gewinnfall geht man zwei Glieder in der Reihe zurück. Das wird solange wiederholt, bis man vor dem ersten Glied landet. Man hat dann wie bei der martingale Strategie genau den Starteinsatz gewonnen. Allerdings ist eine längere Pechstähne nicht so katastrophal wie beim „Martingale“, man bleibt mit der Fibonacci-Strategie in der Regel „länger am Leben“.

Ohne tiefer auf die Vor- und Nachteile der Setzstrategien einzugehen (im wahren Leben werdet ihr mit keiner davon auf Dauer wirklich reich werden können) soll die Programmieraufgabe darin bestehen, alle vier Strategien zu simulieren und statistisch zu bewerten. Folgendes sei vereinbart: Wir starten eine Serie immer mit einem EURO. In der Hinterhand (Startkapital) haben wir z. B. 100 EURO. Eine Serie sei dann beendet, wenn wir entweder alles verloren haben oder mindestens das doppelte Startkapital auf dem Konto haben. Sollten wir bei einer Wette nicht mehr den geforderten Einsatz zur Verfügung haben, so setzen wir soviel, wie noch auf dem Konto ist. Maximal soll eine Wettserie über 1.000 Runden gehen. Unsere Gewinn-/Verlustwahrscheinlichkeit soll variabel zwischen 40 % und 60 % liegen, bei einer Serie allerdings jeweils konstant bleiben.

In den beigefügten Bildern ist exemplarisch dargestellt, wie eine Wettserie im zeitlichen Verlauf etwa aussehen könnte. Das Startkapital war hier auf 1.024 EURO festgelegt worden.
#1
vote_ok
von daniel59 (4260 Punkte) - 30.08.2017 um 15:05 Uhr
MainWindow.xaml.cs
Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfWetteinsatz
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private static readonly Random rnd = new Random();

        private SolidColorBrush brushStatic;
        private SolidColorBrush brushMartingal;
        private SolidColorBrush brushReverseMartingal;
        private SolidColorBrush brushFibonacci;

        private double SKX, SKY;
        private Point ZeroPoint;
        private Simulation[] simulation;



        public MainWindow()
        {
            InitializeComponent();
            brushStatic = (SolidColorBrush)Application.Current.MainWindow.FindResource("brushStatic");
            brushMartingal = (SolidColorBrush)Application.Current.MainWindow.FindResource("brushMartingal");
            brushReverseMartingal = (SolidColorBrush)Application.Current.MainWindow.FindResource("brushReverseMartingal");
            brushFibonacci = (SolidColorBrush)Application.Current.MainWindow.FindResource("brushFibonacci");
        }

        private bool InitGrid(out int rounds, out int budget, out double p, out int luck)
        {
            canvasChart.Children.Clear();
            simulationDataGrid.Items.Refresh();
            bool b = int.TryParse(textBoxMaxRound.Text, out rounds) && int.TryParse(textBoxStartCapital.Text, out rounds) && double.TryParse(textBoxP.Text, out p) && int.TryParse(textBoxLuck.Text, out luck);
            if (!b)
            {
                rounds = 0;
                budget = 0;
                p = 0;
                luck = 0;
                return false;
            }
            rounds = int.Parse(textBoxMaxRound.Text);
            budget = int.Parse(textBoxStartCapital.Text);
            p = double.Parse(textBoxP.Text) / 100.0;
            luck = int.Parse(textBoxLuck.Text);
            canvasChart.UpdateLayout();
            SKX = canvasChart.ActualWidth / rounds;
            SKY = canvasChart.ActualHeight / (2.0 * budget);
            ZeroPoint = new Point(0, canvasChart.ActualHeight / 2);

            Line mid = new Line() { X1 = 0, X2 = canvasChart.ActualWidth, Y1 = canvasChart.ActualHeight / 2, Y2 = canvasChart.ActualHeight / 2, Stroke = Brushes.Black, StrokeThickness = 2 };
            canvasChart.Children.Add(mid);

            return true;
        }

        private Point GetPoint(double X, double Y)
        {
            Point P = new Point();
            P.X = ZeroPoint.X + X * SKX;
            P.Y = ZeroPoint.Y - Y * SKY;
            return P;
        }

        private bool SimulateGame(double winChance)
        {
            double d = rnd.NextDouble();
            return d <= winChance;
        }

        private void buttonStart_Click(object sender, RoutedEventArgs e)
        {
            int round, budget, luck;
            double p;
            simulation = new Simulation[0];
            if (InitGrid(out round, out budget, out p, out luck))
            {
                simulation = new Simulation[round];
                for (int i = 0; i < simulation.Length; i++)
                {
                    simulation[i] = new Simulation() { Wins = SimulateGame(p), Round = i + 1 };
                }
                SimulateStatic(budget);
                SimulateMartingal(budget);
                SimulateReverseMartingal(budget, luck);
                SimulateFibonacci(budget);

            }

            System.Windows.Data.CollectionViewSource simulationViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("simulationViewSource")));
            simulationViewSource.Source = simulation;
            simulationDataGrid.Items.Refresh();
        }

        private void SimulateStatic(int budget)
        {
            Point last = new Point(ZeroPoint.X, ZeroPoint.Y);
            int money = budget;
            int bet = 1;
            for (int i = 0; i < simulation.Length; i++)
            {
                if (money >= budget * 2 || money <= 0)
                {
                    simulation[i].WinStatisch = i - 1 >= 0 ? simulation[i - 1].WinStatisch : 0;
                    continue;
                }
                if (simulation[i].Wins)
                {
                    money += money > bet ? bet : money;
                }
                else
                {
                    money -= money > bet ? bet : money;
                }

                int win = money - budget;
                simulation[i].WinStatisch = win;

                Point p = GetPoint(i, win);
                Line l = new Line() { X1 = last.X, Y1 = last.Y, X2 = p.X, Y2 = p.Y, Stroke = brushStatic, StrokeThickness = 1 };
                canvasChart.Children.Add(l);

                last = p;
            }
        }

        private void SimulateMartingal(int budget)
        {
            Point last = new Point(ZeroPoint.X, ZeroPoint.Y);
            int money = budget;
            int bet = 1;
            for (int i = 0; i < simulation.Length; i++)
            {

                if (money >= budget * 2 || money <= 0)
                {
                    simulation[i].WinMartingal = i - 1 >= 0 ? simulation[i - 1].WinMartingal : 0;
                    continue;
                }
                if (simulation[i].Wins)
                {
                    money += money > bet ? bet : money;

                    bet = 1;
                }
                else
                {
                    money -= money > bet ? bet : money;
                    bet *= 2;
                }

                int win = money - budget;
                simulation[i].WinMartingal = win;

                Point p = GetPoint(i, win);
                Line l = new Line() { X1 = last.X, Y1 = last.Y, X2 = p.X, Y2 = p.Y, Stroke = brushMartingal, StrokeThickness = 1 };
                canvasChart.Children.Add(l);

                last = p;
            }
        }

        private void SimulateReverseMartingal(int budget, int luck)
        {
            Point last = new Point(ZeroPoint.X, ZeroPoint.Y);
            int money = budget;
            int bet = 1;
            int c = 0;
            for (int i = 0; i < simulation.Length; i++)
            {
                if (money >= budget * 2 || money <= 0)
                {
                    simulation[i].WinReverseMartingal = i - 1 >= 0 ? simulation[i - 1].WinReverseMartingal : 0;
                    continue;
                }

                if (simulation[i].Wins)
                {
                    money += money > bet ? bet : money;
                    bet *= 2;
                    c++;
                    if (c >= luck)
                    {
                        bet = 1;
                    }
                }
                else
                {
                    money -= money > bet ? bet : money;
                    bet = 1;
                }

                int win = money - budget;
                simulation[i].WinReverseMartingal = win;

                Point p = GetPoint(i, win);
                Line l = new Line() { X1 = last.X, Y1 = last.Y, X2 = p.X, Y2 = p.Y, Stroke = brushReverseMartingal, StrokeThickness = 1 };
                canvasChart.Children.Add(l);

                last = p;
            }
        }

        private void SimulateFibonacci(int budget)
        {
            Point last = new Point(ZeroPoint.X, ZeroPoint.Y);
            int money = budget;
            int bet = 1;
            List<int> fibonacci = CreateFibonacciList(budget);
            int index = 0;
            for (int i = 0; i < simulation.Length; i++)
            {
                if (money >= budget * 2 || money <= 0)
                {
                    simulation[i].WinFibonacci = i - 1 >= 0 ? simulation[i - 1].WinFibonacci : 0;
                    continue;
                }

                int temp = bet;
                if (simulation[i].Wins)
                {
                    money += money > bet ? bet : money;

                    index -= 2;
                    if (index < 0)
                    { index = 1; }
                    bet = fibonacci[index];
                }
                else
                {
                    money -= money > bet ? bet : money;
                    bet = fibonacci[++index];
                }

                int win = money - budget;
                simulation[i].WinFibonacci = win;

                Point p = GetPoint(i, win);
                Line l = new Line() { X1 = last.X, Y1 = last.Y, X2 = p.X, Y2 = p.Y, Stroke = brushFibonacci, StrokeThickness = 1 };
                canvasChart.Children.Add(l);

                last = p;
            }
        }

        private static List<int> CreateFibonacciList(int max)
        {
            List<int> fibonacci = new List<int>() { 1, 1 };
            int i = 0;

            while (fibonacci.Last() <= max)
            {
                fibonacci.Add(fibonacci.Skip(i++).Take(2).Sum());
            }

            return fibonacci;
        }
    }

    class Simulation
    {
        public int Round { get; set; }
        public int WinStatisch { get; set; }
        public int WinMartingal { get; set; }
        public int WinReverseMartingal { get; set; }
        public int WinFibonacci { get; set; }
        public bool Wins { get; set; }
    }
}


MainWindow.xaml
Quellcode ausblenden XML-Code
<Window x:Class="WpfWetteinsatz.MainWindow"
        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:local="clr-namespace:WpfWetteinsatz"
        mc:Ignorable="d"
        Title="MainWindow" Height="448" Width="843" Background="AliceBlue" ResizeMode="CanMinimize">
    <Window.Resources>
        <SolidColorBrush x:Key="brushStatic" Color="Blue"/>
        <SolidColorBrush x:Key="brushMartingal" Color="Red"/>
        <SolidColorBrush x:Key="brushReverseMartingal" Color="Green"/>
        <SolidColorBrush x:Key="brushFibonacci" Color="Yellow"/>
        <CollectionViewSource x:Key="simulationViewSource" d:DesignSource="{d:DesignInstance {x:Type local:Simulation}, CreateList=True}"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <Grid DataContext="{StaticResource simulationViewSource}">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>
            <Grid Grid.Column="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Grid Grid.Column="0">
                    <TextBox x:Name="textBoxMaxRound" Width="50" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="114,13,0,0" Text="1000" TextAlignment="Center"/>
                    <TextBox x:Name="textBoxStartCapital" Width="50" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="114,37,0,0" Text="1000" TextAlignment="Center"/>
                    <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="10,40,0,0" TextWrapping="Wrap" Text="Startkapital" VerticalAlignment="Top"/>
                    <TextBlock x:Name="textBlock1" HorizontalAlignment="Left" Margin="10,13,0,0" TextWrapping="Wrap" Text="Runden" VerticalAlignment="Top"/>
                    <Button x:Name="buttonStart" Content="Start" HorizontalAlignment="Left" Margin="10,120,0,0" VerticalAlignment="Top" Width="154" Click="buttonStart_Click"/>
                    <TextBox x:Name="textBoxP" HorizontalAlignment="Left" Height="23" Margin="114,64,19,0" TextWrapping="Wrap" Text="50" VerticalAlignment="Top" Width="50" TextAlignment="Center"/>
                    <TextBlock x:Name="textBlock2" HorizontalAlignment="Left" Margin="10,67,0,0" TextWrapping="Wrap" Text="Wahrscheinlichkeit" VerticalAlignment="Top"/>
                    <TextBox x:Name="textBoxLuck" HorizontalAlignment="Left" Height="23" Margin="114,92,0,0" TextWrapping="Wrap" Text="5" VerticalAlignment="Top" Width="50" TextAlignment="Center"/>
                    <TextBlock x:Name="textBlock3" HorizontalAlignment="Left" Margin="10,95,0,0" TextWrapping="Wrap" Text="Glück" VerticalAlignment="Top"/>

                </Grid>
                <Grid Grid.Column="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <StackPanel Orientation="Horizontal" Margin="10,10,0,0" Grid.Row="0">
                        <Ellipse Height="15" Width="15" Fill="{Binding Mode=OneWay, Source={StaticResource brushStatic}}"/>
                        <TextBlock Text="Statisch" Margin="5,0,0,0"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="10,10,0,0" Grid.Row="1">
                        <Ellipse Height="15" Width="15" Fill="{Binding Mode=OneWay, Source={StaticResource brushMartingal}}"/>
                        <TextBlock Text="Martingal" Margin="5,0,0,0"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="10,10,0,0" Grid.Row="2">
                        <Ellipse Height="15" Width="15" Fill="{Binding Mode=OneWay, Source={StaticResource brushReverseMartingal}}"/>
                        <TextBlock Text="Reverse Martingal" Margin="5,0,0,0"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="10,10,0,0" Grid.Row="3">
                        <Ellipse Height="15" Width="15" Fill="{Binding Mode=OneWay, Source={StaticResource brushFibonacci}}"/>
                        <TextBlock Text="Fibonacci" Margin="5,0,0,0"/>
                    </StackPanel>
                </Grid>
            </Grid>
            <DataGrid x:Name="simulationDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Margin="10" RowDetailsVisibilityMode="VisibleWhenSelected" Grid.Row="1" IsReadOnly="True">
                <DataGrid.Columns>
                    <DataGridTextColumn x:Name="roundColumn" Binding="{Binding Round}" Header="Runde" Width="SizeToHeader"/>
                    <DataGridTextColumn x:Name="winStatischColumn" Binding="{Binding WinStatisch}" Header="Statisch" Width="SizeToHeader"/>
                    <DataGridTextColumn x:Name="winMartingalColumn" Binding="{Binding WinMartingal}" Header="Martingal" Width="SizeToHeader"/>
                    <DataGridTextColumn x:Name="winReverseMartingalColumn" Binding="{Binding WinReverseMartingal}" Header="Reverse Martingal" Width="SizeToHeader"/>
                    <DataGridTextColumn x:Name="winFibonacciColumn" Binding="{Binding WinFibonacci}" Header="Fibonacci" Width="SizeToHeader"/>
                    <DataGridCheckBoxColumn x:Name="winsColumn" Binding="{Binding Wins}" Header="Gewonnen" Width="SizeToHeader"/>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
        <Canvas x:Name="canvasChart" Grid.Column="1" Margin="10" Background="LightGray"/>
    </Grid>
</Window>

Kommentare:

Für diese Lösung gibt es noch keinen Kommentar

Bitte melden Sie sich an um eine Kommentar zu schreiben.
Kommentar schreiben