• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eric15342335 / comp2113-engg1340-group-project / #32

17 Jun 2024 01:33PM UTC coverage: 73.604% (+0.1%) from 73.503%
#32

push

travis-ci

eric15342335
Fix undef symbol __imp_ShowWindow on MSVC

1450 of 1970 relevant lines covered (73.6%)

709.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.06
/src/random_price.cpp
1
/// @file random_price.cpp
2
/// Random price generator for stock market simulation
3
/*
4
This program is free software: you can redistribute it and/or modify it under the
5
terms of the GNU Lesser General Public License as published by the Free Software
6
Foundation, either version 3 of the License, or (at your option) any later version.
7

8
This program is distributed in the hope that it will be useful, but WITHOUT ANY
9
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
11

12
You should have received a copy of the GNU Lesser General Public License along with this
13
program. 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

23
float init_stock_price(int price_profile) {
140✔
24
    std::random_device rd;
140✔
25
    std::mt19937 gen(rd());
140✔
26
    std::normal_distribution<float> distribution(5.0, 2.0);
140✔
27
    if (price_profile == 2) {
140✔
28
        distribution.param(std::normal_distribution<float>::param_type(50.0, 20.0));
53✔
29
    }
30
    if (price_profile == 3) {
140✔
31
        distribution.param(std::normal_distribution<float>::param_type(150.0, 50.0));
45✔
32
    }
33
    return std::abs(distribution(gen));
280✔
34
}
140✔
35

36
float init_sd(void) {
140✔
37
    std::random_device rd;
140✔
38
    std::mt19937 gen(rd());
140✔
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);
140✔
42
    return std::abs(distribution(gen)) + 0.5;
280✔
43
}
140✔
44

45
unsigned int random_integer(unsigned int max_integer) {
532✔
46
    // Discrete uniform distribution
47
    // like python randint
48
    std::random_device rd;
532✔
49
    std::mt19937 gen(rd());
532✔
50
    std::uniform_int_distribution<unsigned int> distribution(0, max_integer - 1);
532✔
51
    return distribution(gen);
1,064✔
52
}
532✔
53

54
std::map<stock_modifiers, float> getProcessedModifiers(Stock stock) {
1,960✔
55
    float trueMean = meanMultiplier * (stock.get_total_attribute(mean));
1,960✔
56
    float trueSD = sdMultiplier * (stock.get_total_attribute(standard_deviation));
1,960✔
57
    unsigned int rounds_passed = stock.get_history_size();
1,960✔
58
    if (stock.get_price() < stock.get_initial_price() / 10) {
1,960✔
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) {
1,960✔
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()) /
1,960✔
76
                 stock.get_price();
1,960✔
77
    float upper_lim = stock.get_base_attribute(upper_limit) +
1,960✔
78
                      stock.get_event_attribute(upper_limit) * upperLimitMultiplier +
1,960✔
79
                      std::min(static_cast<int>(rounds_passed / 3), 10) + temp;
1,960✔
80
    float lower_lim = stock.get_base_attribute(lower_limit) +
1,960✔
81
                      stock.get_event_attribute(lower_limit) * lowerLimitMultiplier -
1,960✔
82
                      std::min(static_cast<int>(rounds_passed / 3), 10) - temp;
1,960✔
83
    // Standardize the upper and lower limit
84
    float zScoreUpLimit = (upper_limit - trueMean) / trueSD;
1,960✔
85
    float zScoreLowLimit = (lower_limit - trueMean) / trueSD;
1,960✔
86
    for (int i = 0; i < 10; i++) {
21,560✔
87
        if (zScoreLowLimit > 1.3) {
19,600✔
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;
48✔
91
            zScoreLowLimit = (lower_limit - trueMean - 0.1) / trueSD;
48✔
92
        }
93
        if (zScoreUpLimit < -1.3) {
19,600✔
94
            // Converse
95
            // Reason: for N(0,1), probability of exceeed 1.3 is less that 10%
96
            trueMean -= meanMultiplier;
210✔
97
            zScoreUpLimit = (upper_limit - trueMean + 0.1) / trueSD;
210✔
98
        }
99
    }
100
    // -100% is not applicable for a stock price, so we set it to -90%.
101
    if (lower_lim < -90) {
1,960✔
102
        lower_lim = -90;
×
103
    }
104
    else if (lower_lim > defaultLowerLimit) {
1,960✔
105
        lower_lim = defaultLowerLimit;
×
106
    }
107
    if (upper_lim < defaultUpperLimit) {
1,960✔
108
        upper_lim = defaultUpperLimit;
×
109
    }
110
    return {{standard_deviation, trueSD}, {mean, trueMean}, {lower_limit, lower_lim},
×
111
        {upper_limit, upper_lim}};
1,960✔
112
}
113

114
float percentage_change_price(Stock stock) {
880✔
115
    std::random_device rd;
880✔
116
    std::mt19937 gen(rd());
880✔
117
    std::map<stock_modifiers, float> _modifiers = getProcessedModifiers(stock);
880✔
118
    std::normal_distribution<float> distribution(
119
        _modifiers[mean], _modifiers[standard_deviation]);
880✔
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++) {
966✔
124
        float x = distribution(gen);
966✔
125
        if (x > _modifiers[lower_limit] && x < _modifiers[upper_limit]) {
966✔
126
            return x / std::pow(2, stock.get_split_count());
880✔
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
}
880✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc