3
\$\begingroup\$

I'm attempting to make a stock trading game in Javascript and I've been trying to find an algorithm to generate fake stock prices. Currently, each Stock object has a minimum value, maximum value, and volatility which I will explain later. The code is as follows:

Stock.prototype.generateValue = function () {
    //mod = probability that the value will decrease next turn
    var mod = 0.5;
    if (this.value > this.max) mod = 0.8;
    if (this.value < this.min) mod = 0.2;
    var dir = (Math.random() >= mod) ? 1 : -1;

    //maxToAdd = max amount that the value can change
    var maxToAdd = (this.max - this.min) * this.volatility / 100;
    this.value += (Math.random() * maxToAdd * dir);

    //value can't be 0 -- random number from 0 to 10
    if (this.value < 0) this.value = Math.random()*10;

    //rounds to 2 decimal places
    this.value = (Math.round(100*this.value))/100;
    this.pastValues[this.pastValues.length] = this.value;
    return this.value;
};

Right now, if the current value is within the allowed range (minimum to maximum), then it has a 50% chance of going up and a 50% chance of going down. If it is out of said range, then it has an 80% chance of heading back towards the range and a 20% chance of heading farther out.

Volatility is how much the stock changes on average. Each turn, it changes by a random number between \$0\$ and \$\frac{volatility}{100} \cdot{range}\$ - that is, the volatility is the percentage of the entire range that it can change each turn (if anyone understands this and can explain it better, I would appreciate it).

The results so far have been pretty believable, but if there's any better algorithm that can be found it would be helpful. I would like something that isn't so, well, random. My algorithm stays between the range but there's not a ton of room for something unexpected to happen.

Some screenshots of results (the second is a new chart, but zoomed in on the lower values): Results 1 Results 2

\$\endgroup\$
1
  • 2
    \$\begingroup\$ This question might also be appropriate for Quantitative Finance, if you formulate it in a rigorous enough way. \$\endgroup\$ Commented May 2, 2015 at 0:18

2 Answers 2

4
\$\begingroup\$

This question might be a better fit for another board, since you're asking for different algorithms. CodeReview is more for reviewing your current implementation. As 200_success mentioned, Quantitative Finance can perhaps give you some ideas for what to model, Game Development might have some ideas for "steering" randomness, and of course StackOverflow, if you're unsure of how to implement a different algorithm.

Just know that since it's hideously complicated to make a stock market game that doesn't feel like a total dice roll (and practically impossible to make a truly accurate simulation), most games just use the real stock market but fake money. That way, players have all the right sources of information to help decide their trades, which is the really hard thing to simulate. Will you simulate press releases? Earnings calls? Analyst/stock pundit predictions? The local and global economy? Fraud? Savage rabbits attacking Foxconn's factory and disrupting production for practically every electronics manufacturer in the world? Yeah... it's tough.

And of course, there's the thing that a stock price actually reflects: Trading activity. All the news in the world won't move a stock's price if no one is buying or selling. But it also means that the market is a feedback system, so your players' trades may impact prices (if the trades are large enough). So again: It's hideously complicated.

The best I can offer here is a review of your current code.

  • Your original question's code was very, very dense. You've since added some comments and whitespace, which was otherwise the first thing I'd suggest.

  • Your use of randomness introduces a potential problem: The stock rising or falling forever. Improbable, yes, but possible. You guard against the stock going negative, but still. Your guard mechanism is also a bit blunt. Theoretically a stock could trade below $1 for a while, and then suddenly - because it was about to go negative - it's at $10 regardless of its volatility or range. I'd probably invest in some of those penny stocks, on the off-chance that that happens. You should probably have a mechanism for delisting a stock instead, if it falls too low.

  • With your current solution, there's always at least a 20% chance that the market goes your way. Having 1-in-5 odds isn't great, but in real life there are much worse odds to be had (like betting on a company that's suddenly gone into bankruptcy after an accounting scandal and its CEO being eaten by wombats or something). It just feels like the 20/50/80 odds are a bit too coarse.

  • Having both a min/max price and a "volatility factor" might be redundant. Setting the min/max close to the current price should reduce volatility, and setting them further away should increase volatility. Or you might only use volatility, and let the stock do what it wants with no special min/max.

In terms of code, things look ok, except that this line

this.pastValues[this.pastValues.length] = this.value;

could just be

this.pastValues.push(this.value);

I'd also consider extracting the round-to-two-decimals code, since I'm sure you'll find it useful elsewhere.

As for changes, I'd probably change the price by a percentage instead. That way, it can't fall below zero:

Stock.prototype.generateValue = function () {
  var minPercentage = this.min / this.value,
      maxPercentage = this.max / this.value,
      range = maxPercentage - minPercentage,
      change = Math.random() * range + minPercentage;

  this.value = Math.round(this.value * change * 100) / 100;

  this.pastValues.push(this.value);

  return this.value;
};

Of course, you'll want to continually update the min/max range to "steer" the price one way or the other (just make sure that max >= min >= 0).

Regardless, how you want to do all this really depends on how the game part plays.

\$\endgroup\$
2
  • \$\begingroup\$ Great feedback - I will update my code with pretty much all of this. I don't know how much I could do with the percentage as I'm taking the real stock values and using the past year maximum and minimum. Also, do you think Quantitative Finance or Game Development would react better? The stock part of it has me leaning towards finance, but the whole game part makes me think game development would be better. \$\endgroup\$
    – mdc32
    Commented May 2, 2015 at 13:36
  • \$\begingroup\$ @mdc32 I can't say for sure, they were just ideas. Perhaps quant could give you some ideas for how to model it differently (I'm sure there are plenty of stock-simulation models out there). But it really depends heavily on how you want to go about things; what the "game" part is. It could just be a pure roulette, but I imagine you want players to base their decisions on something, hence you'll have to make sure that the game rewards/punishes those decisions in a fair way by steering the prices. And lets not forget the feedback: Trading activity affects price. \$\endgroup\$
    – Flambino
    Commented May 2, 2015 at 13:53
1
\$\begingroup\$

To make the simulation realistic, there are two additional elements that you need to capture:

  • Stock returns are correlated. A proportion of a stock's returns reflect the trend of the broader market. Read up on alpha and beta.
  • Events. These include earnings releases, earnings estimates, analyst rating changes, credit rating changes, mergers and acquisitions (and rumors thereof), natural disasters, regulatory changes, unemployment reports, commodity price movements, and so on.

Stock prices are a result of a combination of processes. You want to structure your code to be able to accommodate effects from events and broader market movements into the simulation of individual stock prices, and then simulate "the market" as a separate random process.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.