I tried to implement the following functions
The trading API provided by OANDA felt pretty good, so I was able to realize it. In particular, since you can buy and sell in units of one currency (in units of one dollar), even if you move 100 AIs and repeat transactions, the loss will be within a few tens of yen a day. It is safe even if the trading system runs out of control due to a bug during the test. I think it's a good time because I couldn't realize it by myself without this API. http://developer.oanda.com/rest-live/development-guide/
The semi-optimal solution of the optimization problem can be solved in a short time. If you're wondering about optimization problems or sub-optimal solutions, you might be able to find out by watching a video that captures Mario with a genetic algorithm. → [Nico Douga] I tried to learn Super Mario Bros.
While trying Oanda API with curl, I will write it with python when I finish trying
request
curl -X GET "https://api-sandbox.oanda.com/v1/candles?instrument=EUR_USD&count=100&candleFormat=midpoint&granularity=D&dailyAlignment=0&alignmentTimezone=America%2FNew_York"
response
{
"instrument" : "EUR_USD",
"granularity" : "D",
"candles" : [
{
"time" : "2015-06-22T04:00:00.000000Z",
"openMid" : 1.24121,
"highMid" : 1.241535,
"lowMid" : 1.240145,
"closeMid" : 1.24113,
"volume" : 24144,
"complete" : true
}
]
}
Rate acquisition python code
base_domain = MODE.get('production')
url_base = 'https://{}/v1/candles?'.format(base_domain)
url = url_base + 'instrument={}&'.format(currency_pair.name) + \
'count=5000&' +\
'candleFormat=midpoint&' +\
'granularity={}&'.format(granularity.name) +\
'dailyAlignment=0&' +\
'alignmentTimezone=Asia%2FTokyo&' +\
'start={}T00%3A00%3A00Z'.format(start)
response = requests_api(url)
def requests_api(url, payload=None):
auth = 'Bearer {}'.format(get_password('OandaRestAPIToken'))
headers = {'Accept-Encoding': 'identity, deflate, compress, gzip',
'Accept': '*/*', 'User-Agent': 'python-requests/1.2.0',
'Content-type': 'application/json; charset=utf-8',
'Authorization': auth}
if payload:
requests.adapters.DEFAULT_RETRIES = 2
response = requests.post(url, headers=headers, data=payload, timeout=10)
else:
requests.adapters.DEFAULT_RETRIES = 2
response = requests.get(url, headers=headers, timeout=10)
print 'REQUEST_API: {}'.format(url)
return response
■ Specifications Compare the current rate with the 24-hour average rate, and if there is a deviation of 30 pip or more, set the profit margin and loss cut at 30 pip and buy and sell.
■ Operation example Currency: Dollar Yen Current time: October 1, 2015 10:00:00 Current rate: 120.00 yen 24-hour average rate: 119.40 yen Purchase currency unit: 100 Order details: 120 yen for 100 units BUY, profit taking 120.30 yen, loss cut 119.70 yen
code
# -*- coding: utf-8 -*-
import datetime
from enum import Enum
class OrderType(Enum):
Buy = 1
Wait = 0
Sell = -1
class Rate(object):
start_at = datetime.datetime(2015, 10, 1, 10, 0, 0)
bid = float(120.00)
h24 = float(119.40)
base_tick = float(0.01)
@classmethod
def get(cls, currency=None, start_at=None):
return Rate()
def get_rate(self, tick, is_add):
if is_add:
return self.bid + float(tick * self.base_tick)
else:
return self.bid - float(tick * self.base_tick)
class AIOrder(object):
def __init__(self, order_type, limit, stop_limit):
self.order_type = order_type
self.limit = limit
self.stop_limit = stop_limit
class AI(object):
DIFF = 30
LIMIT = 30
STOP_LIMIT = 30
def __init__(self, rate):
self.rate = rate
def order(self):
"""
Order.
"""
if self._can_order():
order(self._get_order())
def _can_order(self):
"""
Can you order or return
rtype: bool
"""
point = (self.rate.bid - self.rate.h24) / self.rate.base_tick
return int(point / self.DIFF) not in [0]
def _get_order(self):
"""
Return order class
rtype: AIOrder
"""
limit_rate = self.rate.get_rate(AI.LIMIT, True)
stop_limit_rate = self.rate.get_rate(AI.STOP_LIMIT, False)
return AIOrder(self._get_order_type(), limit_rate, stop_limit_rate)
def _get_order_type(self):
if self.rate.bid > self.rate.h24:
return OrderType.Buy
if self.rate.h24 > self.rate.bid:
return OrderType.Sell
return OrderType.Wait
def order(ai_order):
_base = "OrderDone:{}, Limit:{}, Stop-Limit:{}"
print _base.format(ai_order.order_type,
ai_order.limit,
ai_order.stop_limit)
#Get rate
rate = Rate.get(currency='USDJPY', start_at=datetime.datetime.now())
#AI generation
ai = AI(rate)
#Order
ai.order()
>>> OrderDone:True, Limit:120.3, Stop-Limit:119.7
Let's benchmark with 5-minute data to see if this AI is a good and profitable AI. I tried to define the definition of excellent AI as follows
Benchmarks that go back in time are called backtests. In the case of program trading, condition 3 is important. Because it's basically left unattended, it makes a lot of money, but I don't like programs that make a lot of losses. 3 is called the maximum drawdown.
Trading AI consists of three parameters. Let's optimize this value. In other words, buying and selling AI was defined as an optimization problem.
class AI(object):
#The factor that determines the order, the difference from the 24h average is more than this value.
DIFF = 30
#Factors that determine the profit taking rate at the time of ordering
LIMIT = 30
#Factors that determine the loss cut rate at the time of ordering
STOP_LIMIT = 30
Assuming that the upper and lower limits of these three parameters are 400 and 10, the number of calculations for all patterns is 390 ^ 3 = 59,319,000 times. If you do a 10-year backtest on a 5-minute bar, it will take about 10 seconds because python is slow to calculate. CPU: The calculation time required for parallel calculation on an 8-core personal computer is as follows. 59,319,000 / 8cpu * 10 seconds / 3600 seconds / 24 hours = 858 days
The calculation time is 858 days. It takes 9 days even if the distribution calculation is performed on 100 PCs. Calculation of all patterns is called linear search.
Well, it's not the number one, but is the AI with the 30th highest profit out of 59,319,000 AIs meaningless? Genetic algorithms work well to find suboptimal solutions.
Determines the rules when calculating with a genetic algorithm.
Calculation efficiency varies depending on the number of individuals and the mutation rate. There are also papers from the perspective of what values should be used for efficiency, so if you are interested, you may want to read them.
If you do not finish the calculation in the 200th generation and evolve it endlessly, it will be partially optimized and the efficiency will drop.
Finally, data like this will be collected.
How to implement crossover / mutation in the genetic algorithm How to generate the initial population Backtest algorithm Actual trading system construction
I haven't finished writing it yet, so I'd like to introduce it in Part 2 at a later date.
Forex automatic trading with genetic algorithm Part 2 Evolving trading AI implementation
Recommended Posts