Artificial Intelligence

Learning How to Develop AI Trading Robots

A Trading Robot Integrated with Neural Network

Fintechee integrates with Synaptic JS which is known as an amazing Javascript library for deep learning. The sample used by this tutorial is implemented by SynapticJS as well. This tutorial will let you know how to convert a webpage to a trained neural network which helps you analyze the market step by step. Please refer to other materials if you want to learn the theory of deep leaning.

Tutorial Video

Neural Network

Neural Network

This sample is implemented by Perceptron, a branch of neural network. Maybe you will ask why not use convolutional NN, which is well-known recently. I think the basic concepts are the same. So, no matter what neural network we are using, our purpose is to make a tool to help us analyze market. And after a long time of practising, we drawed a conclusion that analyzing market is not so sensitive to technical skills. Perceptron is satisfied to help us do that. That's the reason why we don't use complicated neural network structure. In addition, for a beginner, the concept of perceptron is easy to understand. We just need to prepare these stuffs below for constructing a neural network:

  • The number of layers and the number of neurons for every layer.
  • What to input(raw data such as candlestick or indicator).
  • The signal to end up training.

After preparing for the struture of neural network, it's the time to program the EA. The process of developing an EA with AI is simple as well. Please do these things:

  • Write two programs. One is for gathering historical data as input parameters and training. The other one is for calculating the new input parameter by the trained NN model to get signals(buy or sell).
  • Run the first EA to train the NN model.
  • Run the second EA to get signals.

Please check the source codes below as reference:

Training

registerEA(
"sample_training_neuron_model",
"A test EA to train neuron model",
[{
	name: "period",
	value: 20,
	required: true,
	type: "Number",
	range: [1, 100]
}, {
	name: "inputNum",
	value: 20,
	required: true,
	type: "Number",
	range: [1, 100]
}, {
	name: "hiddenNum",
	value: 50,
	required: true,
	type: "Number",
	range: [1, 100]
}, {
	name: "diffPrice",
	value: 0.0001,
	required: true,
	type: "Number",
	range: [0, 10]
}],
function (context) { // Init()
			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			window.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
			var period = getEAParameter(context, "period")
			window.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "rsi", [{
				name: "period",
				value: period
			}])
		},
function (context) { // Deinit()
			var period = getEAParameter(context, "period")
			var inputNum = getEAParameter(context, "inputNum")
			var hiddenNum = getEAParameter(context, "hiddenNum")
			var arrOpen = getData(context, window.chartHandle, DATA_NAME.OPEN)
			var arrClose = getData(context, window.chartHandle, DATA_NAME.CLOSE)
			var arrRsi = getData(context, window.indiHandle, "rsi")

			if (arrRsi.length <= period + 1) return
			if (inputNum + period - 1 > arrRsi.length) throw new Error("No enough data.")

			// extend the prototype chain
			Perceptron.prototype = new synaptic.Network()
			Perceptron.prototype.constructor = Perceptron

			var myPerceptron = new Perceptron(inputNum, hiddenNum, 1)
			var myTrainer = new synaptic.Trainer(myPerceptron)

			var diffPrice = getEAParameter(context, "diffPrice")
			var trainingSet = []
			var longCount = 0
			var shortCount = 0

			for (var i = period - 1; i < arrRsi.length - inputNum; i++) {
				if (arrClose[i * inputNum + inputNum] - arrOpen[i * inputNum + inputNum] > diffPrice) {
					var input = []

					for (var j = 0; j < inputNum; j++) {
						input.push(arrRsi[i * inputNum + j] / 100)
					}

					trainingSet.push({
						input: input,
						output: [0]
					})

					longCount++
				} else if (arrOpen[i * inputNum + inputNum] - arrClose[i * inputNum + inputNum] > diffPrice) {
					var input = []

					for (var j = 0; j < inputNum; j++) {
						input.push(arrRsi[i * inputNum + j] / 100)
					}

					trainingSet.push({
						input: input,
						output: [1]
					})

					shortCount++
				}
			}

			myTrainer.train(trainingSet)
			localStorage.sample_training_neuron_model = JSON.stringify(myPerceptron.toJSON())
			printMessage(longCount + ", " + shortCount)
			printMessage(JSON.stringify(trainingSet))
			printMessage(JSON.stringify(myPerceptron.toJSON()))
		},
function (context) { // OnTick()
})

Running

registerEA(
"sample_run_neuron_model",
"A test EA to run neuron model",
[{
	name: "period",
	value: 20,
	required: true,
	type: "Number",
	range: [1, 100]
}, {
	name: "inputNum",
	value: 20,
	required: true,
	type: "Number",
	range: [1, 100]
}, {
	name: "threshold",
	value: 0.3,
	required: true,
	type: "Number",
	range: [0, 1]
}, {
	name: "takeProfit",
	value: 0.0001,
	required: true,
	type: "Number",
	range: [0, 100]
}],
function (context) { // Init()
			if (typeof localStorage.sample_training_neuron_model == "undefined") return

			window.myPerceptron = synaptic.Network.fromJSON(JSON.parse(localStorage.sample_training_neuron_model))

			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			getQuotes (context, brokerName, accountId, symbolName)
			window.chartHandle = getChartHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1)
			var period = getEAParameter(context, "period")
			window.indiHandle = getIndicatorHandle(context, brokerName, accountId, symbolName, TIME_FRAME.M1, "rsi", [{
				name: "period",
				value: period
			}])
		},
function (context) { // Deinit()
			delete window.currTime
		},
function (context) { // OnTick()
			var arrTime = getData(context, window.chartHandle, DATA_NAME.TIME)
			if (typeof window.currTime == "undefined") {
				window.currTime = arrTime[arrTime.length - 1]
			} else if (window.currTime != arrTime[arrTime.length - 1]) {
				window.currTime = arrTime[arrTime.length - 1]
			} else {
				return
			}

			var account = getAccount(context, 0)
			var brokerName = getBrokerNameOfAccount(account)
			var accountId = getAccountIdOfAccount(account)
			var symbolName = "EUR/USD"

			var period = getEAParameter(context, "period")
			var inputNum = getEAParameter(context, "inputNum")
			var threshold = getEAParameter(context, "threshold")
			var takeProfit = getEAParameter(context, "takeProfit")
			var arrRsi = getData(context, window.indiHandle, "rsi")

			if (inputNum + period - 1 > arrRsi.length) throw new Error("No enough data.")

			var input = []

			for (var i = arrRsi.length - inputNum - 1; i < arrRsi.length - 1; i++) {
				input.push(arrRsi[i] / 100)
			}

			var result = window.myPerceptron.activate(input)[0]
			printMessage(result)

			var ask = getAsk(context, brokerName, accountId, symbolName)
			var bid = getBid(context, brokerName, accountId, symbolName)
			var volume = 0.01

			if (result < 0.5 - threshold) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_BUY, 0, 0, volume, ask+takeProfit, bid-3*takeProfit, "")
			} else if (result > 0.5 + threshold) {
				sendOrder(brokerName, accountId, symbolName, ORDER_TYPE.OP_SELL, 0, 0, volume, bid-takeProfit, ask+3*takeProfit, "")
			}
})