"***********************************************************************************************"

Martingale Betting Strategy

"Instead of traditional recursion, where a function calls itself directly and builds up a call stack, you're calling m(f1) in a way that resets the closure’s state rather than creating new stack frames." -- ChatGPT

The Martingale "Double Your Money" Betting Strategy is, essentially, a system in which players double their bets each time they lose in an even-odds game of chance. Examples are calling "heads" or "tails" on fair flips of a fair coin, and betting on red or black on spins of a roulette wheel.

When "Play" is clicked (below), line 3 of the function "f1" returns either 0 or 1 with equal probability. These numbers are equivalent to false and true in the test on line 4 ("if (result) ...").

Clicing "Play" calls m(f1), where m = M([25,1,25,0]) and x is [25,1,25,0] in the resulting m-M(x) closure. 'x' represents [starting amount, current bet, goal, number of wins], (beginning with [25,1,25,0]).

GAME OUTPUT

  

"********************************************"

Players start with N dollars (m(dF3x)[0] === N), and stop if m(dF3x)[0] reaches 2N. Otherwise, players stop when they wouldn't have enough money to cover losing the next bet; i.e., when m(dF3x)[0] is less than m(dF3x)[1]. Here's the code:

    var log = console.log;
    var dF3x = () => {};

    function M(x) {
        return function go(func) {
            if (func === dF3x) return x;
            x = func(x);
            return go;
        };
    }

    var m = M([25,1,25,0]); // x in the m(x)-M closure is [25,1,25,0]
 // The elements of x (above) represent a starting dollars, first bet, goal, and wins.


    function f1(v) {
        let result = Math.floor(Math.random() * 2);

        if (result) {
            v[0] += v[1];  // Increase stake by current bet
            v[1] = 1;      // Reset bet to 1
            v[3] += 1;     // Increment success counter

            // Recursively continue if stake is less than goal
            if (v[0] < 50) {
                m(f1);  // Continue this round of play
            }
        } else {
            v[0] -= v[1];   // Subtract bet from stake (loss)
            v[1] <<= 1;     // Double the bet (using bit shift)

            // Check if the current bet exceeds stake; if not, continue
            if (v[1] <= v[0]) {
                m(f1);  // Continue playing
            }
        }
    }

Each time a player loses, the amount of the bet (which starts at $1) doubles. If the player wins a bet, all prior losses are recouped and $1 is gained. For example, if the bets were $1, $2, $4,and $8, winning $16 recoups the $(1+2+4+8) = $15, leaving one extra dollar.

When m(dF3x)[3] === m(dF3x)[2], the player's money has doubled because each incremental increase in m(dF3x)[3] corresponds to an incremental increase in m(dF3x)[0]. The final value of x in the m-M(x) closure is m(dF3x) === [50,1,25,25].

If v[3] is less than the starting amount, f1 calls m on itself to initiate another round of action. The semi-recursive function "f1" -- f1 repeatedly calls m(f1), causing f1 to execute on x in the closure -- executes on x until m(dF3x)[2] equals m(dF3x)[3] (Success), or m(dF3x)[0] is less than m(dF3x)[1] (Fail).

Players fail most attempts to double their money. Lacking sufficient funds to cover a losing bet, they leave with whatever they still have. The amount they lose varies, but it's rarely everything they started with.

A BILLION ATTEMPTS TO DOUBLE $50 IN AN m-M(x) CLOSURE

A file named test13.js is shown below. Entering "node test13" in my Linux desktop computer's simulated terminal starts a process that takes about 25 minutes to complete. It uses only 6.2% of the available CPU potential, and a miniscule 60 megabytes of the 64 gigabytes of installed memory. There's obviously no danger of piling too many frames onto the stack.

Here's test13.js:

var log = console.log;
var dF3x = () => {};

function M(x) {
    return function go(func) {
        if (func === dF3x) return x;
        x = func(x);
        return go;
    };
}

function gamble() {
    let m = M([50, 1, 50, 0]);  // [stake, bet, goal, number successes] 
    let gain = 0;
    let loss = 0;
    let k = 0;

    // Main loop
    while (k < 1000000000) {
        k += 1;

        // Place another bet.
        m(f1);
        
        // Reset the closure state in preparation for another round.
        m(() => [50, 1, 50, 0]);
    }

    // Log results after loop
    log("k is", k);
    log("gain is", gain);
    log("loss is", loss);
    log("percent deviation from equality is", ((gain - loss) / (gain + loss)) * 100, "%");

    function f1(v) {
        let result = Math.floor(Math.random() * 2);

        if (result) {
            gain += v[1];
            v[0] += v[1];  // Increase stake by current bet
            v[1] = 1;      // Reset bet to 1
            v[3] += 1;     // Increment success counter

            // Recursively continue if stake is less than goal
            if (v[0] < 100) {
                m(f1);  // Continue playing
            }
        } else {
            v[0] -= v[1];   // Subtract bet from stake (loss)
            loss += v[1];   // Add to total loss
            v[1] <<= 1;     // Double the bet (using bit shift)

            // Check if the current bet exceeds stake; if not, continue
            if (v[1] <= v[0]) {
                m(f1);  // Continue playing
            }
        }
    }
}

gamble();

The result of calling gamble (above) five consecutive times, each time trying to double $50 a billion times, strongly suggests that repeated use of the Martingale betting strategy is a 50-50, break even proposition, similar to betting the same amount on coin flips thousands of times. I don't know how to prove it, but it seems self-evident that no pattern of changing the amounts of bets can possibly increase or decrease the odds of coming out ahead after repeatedly betting on fair flips of a fair coin.

Here are the results:

k is 1000000000
gain is 83168244121
loss is 83169208725
percent deviation from equality is -0.0005799078821370784 %

k is 1000000000
gain is 83171572605
loss is 83170976285
percent deviation from equality is 0.00035848915624969653 %

k is 1000000000
gain is 83168282625
loss is 83170787098
percent deviation from equality is -0.0015056432647907866 %

k is 1000000000
gain is 83169300078
loss is 83170549366
percent deviation from equality is -0.000751045527680717 %

k is 1000000000
gain is 83169558217
loss is 83169526275
percent deviation from equality is 0.000019202943251461886 %