Overall Simulation Control¶
We can now use our collection of classes to generate some more usable results. We can perform a number of simulation runs and evaluate the long-term prospects for the Martingale betting system. We want to know a few things about the game:
How long can we play with a given budget? In other words, how many spins before we’ve lost our stake. The expected value is 38, based on an analysis of the payouts for simple outside (“even money”) bets.
How much we can realistically hope to win? How large a streak can we hope for? How far ahead can we hope to get before we should quit?
In the Simulation Analysis section, we’ll look at general features of simulation.
We’ll look at the resulting statistical data in Statistical Summary.
This will lead us to the details in Simulator Design. We’ll note that
the details of the simulator require some changes to the definition
of the Player
class.
We’ll enumerate all of this chapter’s deliverables in Simulation Control Deliverables.
Simulation Analysis¶
A Simulator
class will be allocated a number of responsibilities:
Simulate a number of sessions of play, saving the maximum stake and length of each session.
For each session: initialize the
Player
and :class: Game objects, cycle the game a number of times, collect the size of thePlayer
object’s stake after each cycle.Write a final summary of the results.
We’ll look at several topics:
Simulation Terms will formalize some definitions.
Simulation Control will look at the overall simulation process.
We’ll look at how we create a new player in Player Initialization.
The most important thing is gather performance data. We’ll look at this in Player Interrogation.
Simulation Terms¶
We’ll try to stick to the following definitions. This will help structure our data gathering and analysis.
cycle
A single cycle of betting and bet resolution. This depends on a single random event: a spin of the wheel or a throw of the dice. Also known as a round of play.
session
One or more cycles. The session begins with a player having their full stake. A session ends when the play elects to leave or can no longer participate. A player may elect to leave because of elapsed time (typically 250 cycles), or they have won a statistically significant amount. A player can no longer participate when their stake is too small to make the minimum bet for the table.
game
Some games have intermediate groupings of events between an individual cycles and an entire session. As cards are dealt in Blackjack, some additional betting opportunities can appear. Similarly, a single game of Craps can involve an indefinite number of dice rolls, each of which offers new betting opportunities.
Simulation Control¶
The sequence of operations for this game simulator looks like this.
Controlling the Simulation
Empty List of Maxima. Create an empty maxima list. This is the maximum stake at the end of each session.
Empty List of Durations. Create an empty durations list. This is the duration of each session, measured in the number of cycles of play before the player withdrew or ran out of money.
For All Sessions. For each of simulated sessions:
Empty List of Stake Details. Create an empty list to hold the history of stake values for this session. This is raw data that we will summarize into two metrics for the session: maximum stake and duration. We could also have two simple variables to record the maximum stake and count the number of spins for the duration. However, the list allows us to gather other statistics, like maximum win or maximum loss.
While The Player Is Active.
Play One Cycle. Play one cycle of the game. See the definition in Roulette Game Class.
Save Outcomes. Save the player’s current stake in the list of stake values for this session. An alternative is to update the maximum to be the larger of the current stake and the maximum, and increment the duration.
Get Maximum. Get the maximum stake from the list of stake values. Save the maximum stake metric in the maxima list.
Get Duration. Get the length of the list of stake values. Save the duration metric in the durations list. Durations less than the maximum mean the strategy went bust.
Statistical Description of Maxima. Compute the average and standard deviation of the values in the maxima list.
Statistical Description of Durations. Compute the average and standard deviation of values in the durations list.
Both this overall Simulator
and the :class: Game classes
collaborate with the Player
class. The Simulator
object’s
collaboration, however, initializes the Player
object and then
monitors the changes to the Player
object’s stake. We have to
design two interfaces for this collaboration.
We’ll look at each of these in separate sections.
Player Initialization¶
The Simulator
class will initialize a Player
instance
for 250 cycles of play, assuming about one cycle each minute, and about
four hours of patience. We will also initialize the player with a
generous budget of the table limit, 100 betting units. For a $10 table,
this is $1,000 bankroll.
Currently, the Player
class is designed to play one session
and stop when their duration is reached or their stake is reduced to
zero. We have two alternatives for reinitializing the Player
object
at the beginning of each session.
The overall simulator control will reset the
stake
androundsToGo
values of aPlayer
instance. This is a matter of setting variables inside thePlayer
object, so there’s nothing to implement here.Provide a Factory that allows a client class to create new, freshly initialized instances of the
Player
class.
While the first solution is quite simple, there are some advantages to
creating a PlayerFactory
class. If we create an
Abstract Factory, we have a single place that creates all Player
instances.
Further, when we add new player subclasses, we introduce these new
subclasses by creating a new subclass of the factory. In this case,
however, only the main program creates instances of the Player
class,
reducing the value of the factory. While design of a Factory is a
good exercise, we can scrape by setting attribute values of a Player
instance.
Player Interrogation¶
The Simulator
object will interrogate the Player
object
after each cycle and capture the current stake. An easy way to manage
this detailed data is to create a list
that contains
the stake at the end of each cycle. The length of this list and the
maximum value in this list are the two metrics the Simulator
gathers for each session.
Our list of maxima and durations are created sequentially during the
session and summarized at the end of the session. A list
will do everything we need. For a deeper discussion on the alternatives
available in the collections framework, see Design Decision – Choosing A Collection.
Statistical Summary¶
While the Simulator
class can interrogate the Player
object
after each cycle to capture the current stake, we don’t want the
sequence of values for each cycle. We want a summary of all the
cycles in the session. We can save the length of the sequence as well as
the maximum of the sequence. We can then calculate aggregate performance
parameters for each session.
Our objective is to run several session
simulations to get averages and a standard deviations for duration and
maximum stake. This means that the Simulator
class needs to
retain these statistical samples. We will defer the detailed design of
the statistical processing, and simply keep the duration and maximum
values in lists for this first round of design.
Simulator Design¶
-
class
Simulator
¶ Simulator
exercises the Roulette simulation with a givenPlayer
placing bets. It reports raw statistics on a number of sessions of play.
Fields¶
-
Simulator.
initDuration
¶ The duration value to use when initializing a
Player
instance for a session. A default value of 250 is a good choice here.
-
Simulator.
initStake
¶ The stake value to use when initializing a
Player
instance for a session. This is a count of the number of bets placed; i.e., 100 $10 bets is $1000 stake. A default value of 100 is sensible.
-
Simulator.
samples
¶ The number of game cycles to simulate. A default value of 50 makes sense.
-
Simulator.
durations
¶ A
list
of lengths of time thePlayer
object remained in the game. Each session of play produces a duration metric, which are collected into this list.
Constructors¶
Methods¶
-
Simulator.
session
(self) → List[int]¶ - Returns
list
of stake values.- Return type
list
Executes a single game session. The
Player
instance is initialized with their initial stake and initial cycles to go. An emptylist
of stake values is created. The session loop executes until thePlayer.playing()
method returns false. This loop executes theGame.cycle()
method; then it gets the stake from thePlayer
and appends this amount to thelist
of stake values. Thelist
of individual stake values is returned as the result of the session of play.
-
Simulator.
gather
(self) → None¶ Executes the number of games sessions in
samples
. Each game session returns alist
of stake values. When the session is over (either the play reached their time limit or their stake was spent), then the length of the session;ist
and the maximum value in the sessionlist
are the resulting duration and maximum metrics. These two metrics are appended to thedurations
list and themaxima
list.A client class will either display the durations and maxima raw metrics or produce statistical summaries.
Simulation Control Deliverables¶
There are five deliverables for this exercise. Each of these classes needs complete Python docstring comments.
Revision to the
Player
class. Don’t forget to update unit tests.The
Simulator
class.The expected outcomes from the non-random wheel can be rather complex to predict. Because of this, one of the deliverables is a demonstration program that enumerates the actual sequence of non-random spins. From this we can derive the sequence of wins and losses, and the sequence of
Player
bets. This will allow us to predict the final outcome from a single session.A unit test of the
Simulator
class that uses the non-random generator to produce the predictable sequence of spins and bets.A main application function that creates the necessary objects, runs the
Simulator
’sgather()
method, and writes the available outputs tosys.stdout
For this initial demonstration program, it should simply print the list of maxima, and the list of session lengths. This raw data can be redirected to a file, loaded into a spreadsheet and analyzed.