Java :: Aufgabe #178

1 Lösung Lösung öffentlich

Wetteinsatzstrategien: statisch, martingal, reverse-martingal oder Fibonacci

Fortgeschrittener - Java 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.

Lösungen:

vote_ok
von PC-principal (1340 Punkte) - 02.08.2017 um 17:14 Uhr
Quellcode ausblenden Java-Code

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

public class Hauptprogramm {

	public static void main(String[] args) {
		int maxSerie = 1000;
		int gewinnwahrscheinlichkeit;

		do {
			gewinnwahrscheinlichkeit = (int) (Math.random() * 100);
		} while (gewinnwahrscheinlichkeit >= 60 || gewinnwahrscheinlichkeit <= 40);

		ArrayList<ZweiwertigesGlueckspiel> glueckspiele = new ArrayList<ZweiwertigesGlueckspiel>();

		glueckspiele.add(new ZweiwertigesGlueckspiel(new statisch(), maxSerie, Color.BLACK));
		glueckspiele.add(new ZweiwertigesGlueckspiel(new martingal(), maxSerie, Color.GREEN));
		glueckspiele.add(new ZweiwertigesGlueckspiel(new reverse_martingal(), maxSerie, Color.BLUE));
		glueckspiele.add(new ZweiwertigesGlueckspiel(new Fibonacci(), maxSerie, Color.RED));

		boolean gewonnen;
		List<Integer> pleite = new ArrayList();

		for (int p = 0; p < maxSerie; p++) {
			if (((int) (Math.random() * 100) - gewinnwahrscheinlichkeit) <= 0) {
				gewonnen = true;
			} else {
				gewonnen = false;
			}

			for (int i = 0; i < glueckspiele.size(); i++) {
				try {
					if (!pleite.contains(i))
						glueckspiele.get(i).neuerZug(gewonnen);
				} catch (Exception e) {
					pleite.add(i);
				}
			}
		}

		Anzeige anzeige = new Anzeige(glueckspiele, gewinnwahrscheinlichkeit);
	}
}


import java.awt.Color;

public class ZweiwertigesGlueckspiel {
	private int runde = 0;
	private int gesetztesGeld = 1000;
	private int kontostand = gesetztesGeld;
	private int maxRunde;
	private int[] kontostandVerlauf;
	private int gewinnSerie = 0;
	private int einsatz = 1;
	private int[] einsatzVerlauf;
	boolean gewonnen;
	private Color graphFarbe;
	private IStrategie strategie;

	public ZweiwertigesGlueckspiel(IStrategie strategie, int maxSerie, Color c) {
		this.strategie = strategie;
		this.maxRunde = maxSerie;
		kontostandVerlauf = new int[maxSerie];
		kontostandVerlauf[0] = gesetztesGeld;
		this.graphFarbe = c;
		this.einsatzVerlauf = new int[maxSerie];
	}

	protected int neuerZug(boolean gewonnen) throws Exception {
		kontostand = strategie.neuerZug(this, gewonnen);
		runde++;
		kontostandVerlauf[runde] = kontostand;
		einsatzVerlauf[runde] = einsatz;
		return kontostand;
	}

	public int getRunde() {
		return runde;
	}
	public void setRunde(int runde) {
		this.runde = runde;
	}
	public int getGesetztesGeld() {
		return gesetztesGeld;
	}
	public void setGesetztesGeld(int gesetztesGeld) {
		this.gesetztesGeld = gesetztesGeld;
	}
	public int getKontostand() {
		return kontostand;
	}
	public void setKontostand(int kontostand) {
		this.kontostand = kontostand;
	}
	public int getMaxRunde() {
		return maxRunde;
	}
	public void setMaxRunde(int maxRunde) {
		this.maxRunde = maxRunde;
	}
	public int[] getVerlauf() {
		return kontostandVerlauf;
	}
	public void setVerlauf(int[] verlauf) {
		this.kontostandVerlauf = verlauf;
	}
	public int getGewinnSerie() {
		return gewinnSerie;
	}
	public void setGewinnSerie(int gewinnSerie) {
		this.gewinnSerie = gewinnSerie;
	}
	public int getEinsatz() {
		return einsatz;
	}
	public void setEinsatz(int einsatz) {
		this.einsatz = einsatz;
	}
	public IStrategie getStrategie() {
		return strategie;
	}
	public void setStrategie(IStrategie strategie) {
		this.strategie = strategie;
	}
	public Color getGraphFarbe() {
		return graphFarbe;
	}
	public void setGraphFarbe(Color graphFarbe) {
		this.graphFarbe = graphFarbe;
	}
	public int[] getEinsatzVerlauf() {
		return einsatzVerlauf;
	}
	public void setEinsatzVerlauf(int[] einsatzVerlauf) {
		this.einsatzVerlauf = einsatzVerlauf;
	}
}


public interface IStrategie {
	int neuerZug(ZweiwertigesGlueckspiel glueck, boolean gewinn) throws Exception;
}


public class statisch implements IStrategie {
	public int neuerZug(ZweiwertigesGlueckspiel glueck, boolean gewonnen) throws Exception {
		if (glueck.getKontostand() > 0 && glueck.getKontostand() < (glueck.getGesetztesGeld() * 2)) {
			if (gewonnen) {
				return (glueck.getKontostand() + glueck.getEinsatz());
			} else {
				return (glueck.getKontostand() - glueck.getEinsatz());
			}
		} else
			throw new Exception("Kein neuer Zug möglich");
	}

	public String toString() {
		return "statisch";
	}
}


public class martingal implements IStrategie {
	public int neuerZug(ZweiwertigesGlueckspiel glueck, boolean gewonnen) throws Exception {
		if (glueck.getKontostand() > 0 && glueck.getKontostand() < (glueck.getGesetztesGeld() * 2)) {
			if (gewonnen) {
				int gewinn = glueck.getKontostand() + glueck.getEinsatz();
				glueck.setEinsatz(1);
				return gewinn;
			} else {
				int verlust = glueck.getKontostand() - glueck.getEinsatz();
				if (glueck.getEinsatz() * 2 < glueck.getKontostand()) {
					glueck.setEinsatz(glueck.getEinsatz() * 2);
				} else {
					glueck.setEinsatz(glueck.getKontostand());
				}
				return verlust;
			}
		} else
			throw new Exception("Kein neuer Zug möglich");
	}

	public String toString() {
		return "martingal";
	}
}


public class reverse_martingal implements IStrategie {
	public int neuerZug(ZweiwertigesGlueckspiel glueck, boolean gewonnen) throws Exception {
		int angestrebteGewinnSerie = 5;
		if (glueck.getKontostand() > 0 && glueck.getKontostand() < (glueck.getGesetztesGeld() * 2)) {
			if (gewonnen) {
				int gewinn = glueck.getKontostand() + glueck.getEinsatz();
				glueck.setGewinnSerie(glueck.getGewinnSerie() + 1);
				if (glueck.getGewinnSerie() < angestrebteGewinnSerie) {
					if (glueck.getKontostand() < glueck.getEinsatz() * 2) {
						glueck.setEinsatz(glueck.getKontostand());
					}
					glueck.setEinsatz(glueck.getEinsatz() * 2);
				} else {
					glueck.setEinsatz(1);
				}
				return gewinn;
			} else {
				int verlust = glueck.getKontostand() - glueck.getEinsatz();
				glueck.setEinsatz(1);
				glueck.setGewinnSerie(0);
				return verlust;
			}
		} else
			throw new Exception("Kein neuer Zug möglich");
	}

	public String toString() {
		return "reverse-martingal";
	}
}


public class Fibonacci implements IStrategie {
	private int fiboEinsatz[] = new int[20];
	int position = 1;

	public Fibonacci() {
		fiboEinsatz[0] = 1;
		fiboEinsatz[1] = 1;
		for (int i = 2; i < 20; i++) {
			fiboEinsatz[i] = fiboEinsatz[i - 1] + fiboEinsatz[i - 2];
		}
	}

	public int neuerZug(ZweiwertigesGlueckspiel glueck, boolean gewonnen) throws Exception {
		if (glueck.getKontostand() > 0 && glueck.getKontostand() < (glueck.getGesetztesGeld() * 2)) {
			if (gewonnen) {
				int gewinn = glueck.getKontostand() + glueck.getEinsatz();
				if (!(position <= 1))
					position = position - 2;
				if (fiboEinsatz[position] <= glueck.getKontostand()) {
					glueck.setEinsatz(fiboEinsatz[position]);
				} else {
					glueck.setEinsatz(glueck.getKontostand());
				}
				return gewinn;
			} else {
				int verlust = glueck.getKontostand() - glueck.getEinsatz();
				position++;
				if (fiboEinsatz[position] <= glueck.getKontostand()) {
					glueck.setEinsatz(fiboEinsatz[position]);
				} else {
					glueck.setEinsatz(glueck.getKontostand());
				}
				return verlust;
			}
		} else
			throw new Exception("Kein neuer Zug möglich");
	}

	public String toString() {
		return "Fibonacci";
	}
}


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Anzeige extends JFrame {
	ArrayList<ZweiwertigesGlueckspiel> data = new ArrayList<ZweiwertigesGlueckspiel>();

	public Anzeige(ArrayList<ZweiwertigesGlueckspiel> glueckspiele, int gewinnwahrscheinlichkeit) {
		this.add(new Chart());
		this.setVisible(true);
		this.setSize(1100, 700);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		data = glueckspiele;
		this.setTitle("Gesetztes Geld:" + data.get(0).getGesetztesGeld() + "   Gewinnwahrscheinlichkeit: "
				+ gewinnwahrscheinlichkeit);
	}

	private class Chart extends JPanel {

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.setColor(Color.BLACK);

			Graphics2D g2d = (Graphics2D) g;

			for (int i = 0; i <= 1000; i += 100) {
				g2d.drawLine(0, (this.getHeight() / 2) + i / 4, this.getWidth(), (this.getHeight() / 2) + i / 4);
				g2d.drawLine(0, (this.getHeight() / 2) - i / 4, this.getWidth(), (this.getHeight() / 2) - i / 4);
				g2d.drawString("+" + i, 0, (this.getHeight() / 2) - i / 4);
				g2d.drawString("" + i * -1, 0, (this.getHeight() / 2) + i / 4);
			}

			for (int i = 0; i <= 1000; i += 100) {
				g2d.drawString("" + i, 0 + i, (this.getHeight() / 2) + 250);
			}

			Font font = g.getFont().deriveFont(20.0f);
			g2d.setFont(font);
			g2d.drawString("Runden", this.getWidth() / 2, (this.getHeight() / 2) + 275);
			g2d.drawString("Gewinn", 0, (this.getHeight() / 2) - 275);

			BasicStroke stroke = new BasicStroke(2);
			g2d.setStroke(stroke);

			for (int i = 0; i < data.size(); i++) {
				g2d.setColor(data.get(i).getGraphFarbe());
				g2d.drawString("" + data.get(i).getStrategie(), 100 + i * this.getWidth() / 4,
						(this.getHeight() / 2) - 275);

				for (int p = 0; p < data.get(i).getMaxRunde() - 1; p++) {
					g2d.drawLine(p,
							(this.getHeight() / 2)
									+ (((data.get(i).getVerlauf())[p] - data.get(i).getGesetztesGeld()) / 4) * -1,
							p + 1, (this.getHeight() / 2)
									+ (((data.get(i).getVerlauf())[p + 1] - data.get(i).getGesetztesGeld()) / 4) * -1);
				}
			}

			this.setBackground(Color.WHITE);
			this.setVisible(true);
			this.setSize(super.getSize());
		}
	}
}