Moving-average crossover strategy assumes that we can detect the change in overall trend by catching it early on a shorter time frame.

entry position (white dot) and exit position (yellow square)

In the code, using the Badger algo-trading framework, we’re comparing 10 and 20-candle moving average (those are 1-minute candles).

First we need to verify that the ma10 is below the ma20. Then once it goes above ma20, the trade is executed.

// MOVING_AVERAGE CROSSOVER STRATEGY

bool hasOpenPosition() {
	return 
		this.positions.length != 0 &&
		this.positions[$-1].action == Action.OPEN;
}

int trades = 0;
bool canTrade = false;

override bool trade() {
	if(!super.trade()) return false;
	// ALL CODE HERE - BEGIN //

	if (trades >= 1 && !hasOpenPosition()) {
		return false; // stop the bot
	}

	Candle[] btcCandles = this.candles[c.BTCUSDT];
	double currentPrice = btcCandles[$-1].close;

	double ma10 = btcCandles[$-11..$-1].map!(c => c.close).array.sum / 10;
	double ma20 = btcCandles[$-21..$-1].map!(c => c.close).array.sum / 20;

	if (!canTrade && !hasOpenPosition && ma10 < ma20) {
		// allow trading after ma10 "resets" below ma20
		// so we can capture the crossover when ma10 becomes > ma20
		canTrade = true;
	}

	if (
		canTrade &&
		!hasOpenPosition() &&
		ma10 > ma20
	) {
		pp("ma10: ", ma10, " - ma20: ", ma20);
		Order marketBuy = Order(
			c.BTCUSDT,
			OrderType.MARKET,
			Direction.BUY,
			currentPrice * 1.003, // target price
			currentPrice * 0.995, // stop price
		);
		this.order(marketBuy);
		canTrade = false;
		trades++;
	}

	// ALL CODE HERE - END //
	return true;
}