(this is part 5 of the “AI for Finance Course“)

Now we’re going to apply this knowledge for training our single neuron (perceptron) to the real market.
(specifically, Bitcoin price)

The most simple thing we can do is to use previous candle to predict the next candle. And we’re not going to complicate much with the exact price. We’re just going to try to predict whether the next candle is RED or GREEN.

The output for red is going to be 0 and the output for GREEN is going to be 1.

Preparing The Inputs

First we need to transform the candle into something manageable. Something that the neuron will be able to easily digest.

One idea (which is not the only one, nor best one, perhaps not even good one) is to capture candle high, low, and close as relevant inputs.

The thinking is that this indicates market movement and might tell us something about what’s going to happen to the next candle.

Entire candle is defined by the relative movement compared to the open price. Here I took the Bitcoin price around 50k for ease of calculation (who knows what’s the price today, could be 5k could be 500k)

INPUT1 = HIGH / OPEN
INPUT2 = LOW / OPEN
INPUT3 = CLOSE / OPEN

And since each individual candle doesn’t move much (especially the minute candles I’m going to use) the input values will be nicely distributed around the value of 1.

Putting This Into Code

As you will see, the code didn’t change much from out previous lesson. The only real difference is now we have 3 inputs (4 if you count the constant) and 4 weights.

However…

I am using the algo-trading framework that downloads the data automatically and generates candles for me.

You do NOT NEED this framework in order to follow along with this course.

But, I will be using it because it allows me to easily…

  • get & save the data
  • load the data in any candle format
    • (from 1-min to 7-day candles)
  • make trades and backtest the bot
  • deploy the bot live with a single line of code

…which is why I developed it from scratch.

// SINGLE NEURON MARKET PREDICTIONS

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

int trades = 0;
bool isAIrained = false;
double[] weights = [0.5, 0.5, 0.5, 0.5]; // N + 1 weights

double sigmoid(double input) { return (tanh(input) + 1) / 2.0; }

double[4] getInputs(Candle c) {
	double[3] rawInputs = ([c.high, c.low, c.close] - c.open) / c.open;
	double[4] inputs = [1.0] ~ rawInputs;
	return inputs;
}

Color getPredictedColor(double prediction) {
	return (prediction > 0.5) ? Color.GREEN : Color.RED;
}

void updateWeights(double prediction, Candle candle, Candle nextCandle) {
	double error = to!double(to!int(nextCandle.color)) - prediction;
	double[4] inputs = getInputs(candle);
	double[4] corrections = inputs[] * error;
	weights[] += corrections[];
}

double getPrediction(Candle candle) {
	double[4] inputs = getInputs(candle);
	double[4] weightedInputs = inputs[] * weights[];
	double weightedSum = weightedInputs.array.sum;
	double prediction = sigmoid(weightedSum);
	return prediction;
}

void trainNetwork(Candle[] trainingCandles) {
	for (int n = 0; n < 100; n++) { // 100 times through the data
		for (int i = 1; i < trainingCandles.length; i++) {
			double prediction = getPrediction(trainingCandles[i-1]);
			updateWeights(prediction, trainingCandles[i-1], trainingCandles[i]);
		}
	}
	pp("weights: ", weights);
	pp();
}


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

	if (!isAIrained) {
		trainNetwork(this.candles[c.BTCUSDT][$-100..$-1]);
		isAIrained = true;
	}

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

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

	Candle lastCandle = btcCandles[$-2];
	double prediction = getPrediction(lastCandle);
	Color predictedNextCandleColor = getPredictedColor(prediction);

	if (
		predictedNextCandleColor == Color.GREEN &&
		!hasOpenPosition()
	) {
		Order marketBuy = Order(
			c.BTCUSDT,
			OrderType.MARKET,
			Direction.BUY,
			currentPrice * 1.003, // target price = +0.3%
			currentPrice * 0.995, // stop price   = -0.5%
		);
		this.order(marketBuy);
		trades++;
	}

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

Code Explanation

So I’m trying to predict the next candle, and if the next candle is GREEN then I open a position with:

  • +0.3% target price
  • -0.5% stop price

Now I know this doesn’t make much sense because even if the next candle is GREEN, the overall price might fall.

And this is something our neuron was NOT trained for to predict.

I KNOW.

But for now we’re just making small steps so we can have bitesized lessons that are easy to grasp.

In the next lessons we’re going to address this issue and make our bot better and better.

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

Bot Performance

As you might expect, the bot completely blew up my account.
(fictional test account, no worries)

Here are the results:

----------------------------
| PERFORMANCE    |
----------------------------
- Initial capital: 100000.00
- Final capital::: 998.74
- Total trades:::: 2401

- ROI:::::: -99.00 %
- Min. ROI: -99.00 %
- Max. ROI: 0.30 %

- Drawdown: -99.00 %
- Pushup::: 1.51 %
----------------------------

As part of this backtest, a transaction fee (0.1%) is included for every buy or sell. This imitates current rates on Binance.
(since this is where I’m going to deploy my bot eventually)

To see why I decided to go with crypto trading instead of pursuing other options like stocks or options, check out this video.

However… I always like to see how the bot would perform if it wasn’t encumbered with the transaction fees… and these are the results:

----------------------------
| PERFORMANCE    |
----------------------------
- Initial capital: 100000.00
- Final capital::: 105146.83
- Total trades:::: 6324

- ROI:::::: 5.15 %
- Min. ROI: -15.29 %
- Max. ROI: 39.66 %

- Drawdown: -29.13 %
- Pushup::: 64.87 %
----------------------------

Surprisingly, it actually did quite well. This is a test on the minute candle data (BTCUSDT) for the first 4 months of 2024.
(so you know which data to use if you want to compare the results)