Stock Market Simulator main e8c3612
A game that provides a realistic stock buying experience with unpredictable trends to test investment strategies.
Loading...
Searching...
No Matches
random_price.cpp
Go to the documentation of this file.
1/// @file random_price.cpp
2/// Random price generator for stock market simulation
3/*
4This program is free software: you can redistribute it and/or modify it under the
5terms of the GNU Lesser General Public License as published by the Free Software
6Foundation, either version 3 of the License, or (at your option) any later version.
7
8This program is distributed in the hope that it will be useful, but WITHOUT ANY
9WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
11
12You should have received a copy of the GNU Lesser General Public License along with this
13program. If not, see <https://www.gnu.org/licenses/>.
14*/
15#include "random_price.h"
16
17#include <algorithm>
18#include <cstdlib>
19#include <random>
20// Included iostream for debugging uses.
21#include <iostream>
22
23float init_stock_price(int price_profile) {
24 std::random_device rd;
25 std::mt19937 gen(rd());
26 std::normal_distribution<float> distribution(5.0, 2.0);
27 if (price_profile == 2) {
28 distribution.param(std::normal_distribution<float>::param_type(50.0, 20.0));
29 }
30 if (price_profile == 3) {
31 distribution.param(std::normal_distribution<float>::param_type(150.0, 50.0));
32 }
33 return std::abs(distribution(gen));
34}
35
36float init_sd(void) {
37 std::random_device rd;
38 std::mt19937 gen(rd());
39 // The old distribution was 0.5, 0.5.
40 // After applying std::abs(), the distribution is not symmetric anymore.
41 std::normal_distribution<float> distribution(0, 0.5);
42 return std::abs(distribution(gen)) + 0.5;
43}
44
45unsigned int random_integer(unsigned int max_integer) {
46 // Discrete uniform distribution
47 // like python randint
48 std::random_device rd;
49 std::mt19937 gen(rd());
50 std::uniform_int_distribution<unsigned int> distribution(0, max_integer - 1);
51 return distribution(gen);
52}
53
54std::map<stock_modifiers, float> getProcessedModifiers(Stock stock) {
55 float trueMean = meanMultiplier * (stock.get_total_attribute(mean));
56 float trueSD = sdMultiplier * (stock.get_total_attribute(standard_deviation));
57 unsigned int rounds_passed = stock.get_history_size();
58 if (stock.get_price() < stock.get_initial_price() / 10) {
59 // Force the return of a significantly higher mean normal dist, by a bit over
60 // doubling the price.
61 trueMean += 200;
62 }
63 else if (stock.get_price() < stock.get_initial_price() / 7) {
64 trueMean += 100;
65 }
66 /* There is a upper limit and lower limit that the realisation of the % change must
67 * fall between. As each round pass we allow for more and more chaotic behaviour by
68 * making the bounds less tight.
69 * Just for fun (chaotic evil smirk). Upon devastating events which leads to
70 * a stock price only 10 % left of it's initial, we increase mean to prevent a game
71 * over. Upon we are 90.32% sure the bounds would be wrong we bump the mean.
72 */
73 // temp is the percentage difference between the initial price and the current price
74 // of the stock.
75 float temp = 100 * std::abs(stock.get_initial_price() - stock.get_price()) /
76 stock.get_price();
77 float upper_lim = stock.get_base_attribute(upper_limit) +
79 std::min(static_cast<int>(rounds_passed / 3), 10) + temp;
80 float lower_lim = stock.get_base_attribute(lower_limit) +
82 std::min(static_cast<int>(rounds_passed / 3), 10) - temp;
83 // Standardize the upper and lower limit
84 float zScoreUpLimit = (upper_limit - trueMean) / trueSD;
85 float zScoreLowLimit = (lower_limit - trueMean) / trueSD;
86 for (int i = 0; i < 10; i++) {
87 if (zScoreLowLimit > 1.3) {
88 // Very likely to fail lower_limit; about 90.32%; which means it is too low
89 // and should realize at higher value;
90 trueMean += meanMultiplier;
91 zScoreLowLimit = (lower_limit - trueMean - 0.1) / trueSD;
92 }
93 if (zScoreUpLimit < -1.3) {
94 // Converse
95 // Reason: for N(0,1), probability of exceeed 1.3 is less that 10%
96 trueMean -= meanMultiplier;
97 zScoreUpLimit = (upper_limit - trueMean + 0.1) / trueSD;
98 }
99 }
100 // -100% is not applicable for a stock price, so we set it to -90%.
101 if (lower_lim < -90) {
102 lower_lim = -90;
103 }
104 else if (lower_lim > defaultLowerLimit) {
105 lower_lim = defaultLowerLimit;
106 }
107 if (upper_lim < defaultUpperLimit) {
108 upper_lim = defaultUpperLimit;
109 }
110 return {{standard_deviation, trueSD}, {mean, trueMean}, {lower_limit, lower_lim},
111 {upper_limit, upper_lim}};
112}
113
115 std::random_device rd;
116 std::mt19937 gen(rd());
117 std::map<stock_modifiers, float> _modifiers = getProcessedModifiers(stock);
118 std::normal_distribution<float> distribution(
119 _modifiers[mean], _modifiers[standard_deviation]);
120 // std::cout << offset << " " << sd << " " << lower_lim << " " << upper_lim <<
121 // std::endl; Implementing a max loop here so will not be infinite if there is a
122 // fault.
123 for (unsigned int max_loop = 0; max_loop < 100; max_loop++) {
124 float x = distribution(gen);
125 if (x > _modifiers[lower_limit] && x < _modifiers[upper_limit]) {
126 return x / std::pow(2, stock.get_split_count());
127 }
128 }
129 // Need to have some stocastic behavour against a fault.
130 float stocastics[12] = {0.95507, -0.74162, 1.642, -0.94774, -0.80314, 1.7885,
131 -0.09846, 1.4693, 0.19288, -1.70222, 1.20933, -0.71088};
132 return stocastics[random_integer(12)];
133}
A class that represents a stock object in the game.
Definition stock.h:55
unsigned int get_split_count(void)
Get the split count of the stock.
Definition stock.h:225
float get_initial_price(void)
Get the initial price of the stock.
Definition stock.h:183
unsigned int get_history_size(void)
Get size of the history.
Definition stock.h:199
float get_total_attribute(stock_modifiers attribute)
Sums up get_base_attribute() and get_event_attribute().
Definition stock.cpp:317
float get_base_attribute(stock_modifiers attribute)
Get the base value of stock_attributes of the stock.
Definition stock.h:191
float get_price(void)
Get the price of the stock.
Definition stock.h:165
float get_event_attribute(stock_modifiers attribute)
Get the total change of attribute of the stock due to events only.
Definition stock.cpp:259
constexpr float meanMultiplier
Multiplier for mean.
Definition events.h:52
const float sdMultiplier
Multiplier for standard deviation.
Definition events.h:55
@ upper_limit
The upper limit of the stock price percentage change.
Definition events.h:48
@ standard_deviation
Amount of variation of the stock price percentage change.
Definition events.h:32
@ mean
The expectation of the stock price percentage change.
Definition events.h:36
@ lower_limit
The lower limit of the stock price percentage change.
Definition events.h:42
const float defaultUpperLimit
Default upper limit.
Definition events.h:67
const float defaultLowerLimit
Default lower limit.
Definition events.h:64
const float upperLimitMultiplier
Upper limit multiplier.
Definition events.h:61
const float lowerLimitMultiplier
Lower limit multiplier.
Definition events.h:58
float init_stock_price(int price_profile)
Initialize starting stock price.
float percentage_change_price(Stock stock)
Calculate the percentage change of the stock price.
std::map< stock_modifiers, float > getProcessedModifiers(Stock stock)
Get the processed modifiers for the stock.
unsigned int random_integer(unsigned int max_integer)
python randint like function
float init_sd(void)
Initialize the standard deviation of the stock price.
Header file for random related functions.