The Oanda API
The configparser module is used to manage account credentials.
Filename: pyalgo.cfg
account_id = YOUR_ACCOUNT_ID
access_token = YOUR_ACCESS_TOKEN
account_type = practice
To access the API via Python, it is recommended to use the Python wrapper package tpqoa.
pip install git+https://github.com/yhilpisch/tpqoa.git
import tpqoa
api = tpqoa.tpqoa('../pyalgo.cfg')
Retrieving Historical Data
Looking up instruments available for trading
api.get_instruments()[:15]
Backtesting a momentum strategy on minute bars
help(api.get_history)
instrument = 'EUR_USD'
start = '2020-08-10'
end = '2020-08-12'
granularity = 'M1'
price = 'M'
data = api.get_history(instrument, start, end, granularity, price)
data.info()
data[['c', 'volume']].head()
Implement the vectorised backtesting
import numpy as np
data['returns'] = np.log(data['c'] / data['c'].shift(1))
cols = []
for momentum in [15, 30, 60, 120]:
col = 'positions_{}'.format(momentum)
data[col] = np.sign(data['returns'].rolling(momentum).mean())
cols.append(col)
The derivation and plotting of the absolute performance of the different momentum strategies
from pylab import plt
plt.style.use('seaborn')
import matplotlib as mpl
mpl.rcParams['savefig.dpi'] = 300
mpl.rcParams['font.family'] = 'serif'
strats = ['returns']
for col in cols:
strat = 'strategy_{}'.format(col.split('_')[1])
data[strat] = data[col].shift(1) * data['returns']
strats.append(strat)
data[strats].dropna().cumsum().apply(np.exp).plot(figsize=(10, 6))
Factoring in leverage and margin
The amplifying effect on the performance of the momentum strategies for a leverage ratio of 20:1.
The initial margin of 5% suffices to cover potential losses
data[strats].dropna().cumsum().apply(lambda x: x * 20).apply(np.exp).plot(figsize=(10, 6))
Working with streaming data
instrument = 'EUR_USD'
api.stream_data(instrument, stop=10)
Placing market orders
help(api.create_order)
api.create_order(instrument, 1000)
api.create_order(instrument, -1500)
api.create_order(instrument, 500)
Implementing trading strategies in real time
import tpqoa
import numpy as np
import pandas as pd
class MomentumTrader(tpqoa.tpqoa)
def __init__(self. conf_file, instrument, bar_length, momentum, units, *args, **kwargs):
super(MomentumTrader, self).__init__(conf_file)
self.position = 0
self.instrument = instrument
self.momentum = momentum
self.bar_length = bar_length
self.units = units
self.raw_data = pd.DataFrame()
self.min_length = self.momentum + 1
Implements the trading logic for the momentum strategy
def on_success(self, time, bid, ask):
// Takes actions when new tick data arrives.
print(self.ticks, end='')
self.raw_data = self.raw_data.append(pd.DataFrame({'bid': bid, 'ask': ask}, index=[pd.Timestramp(time)]))
self.data = self.raw_data.resample(self.bar_length, label='right').last().ffill().iloc[:-1]
self.data['mid'] = self.data.mean(axis=1)
self.data['returns'] = np.log(self.data['mid'] / self.data['mid'].shift(1))
self.data['position'] = np.sign(self.data['returns'].rolling(self.momentum).mean())
if len(self.data) > self.min_length:
self.min_length += 1
if self.data['position'].iloc[-1] == 1:
if self.position == 0:
self.create_order(self.instrument, self.units)
elif self.position == -1:
self.create_order(self.instrument, self.units * 2)
self.position = 1
elif self.data['position'].iloc[-1] == -1:
if self.position == 0:
self.create_order(self.instrument, -self.units)
elif self.position == 1:
self.create_order(self.instruemnt, -self.units * 2)
self.position = -1
Getting started with automated
import MomentumTrader as MT
mt = MT.MomentumTrader('../pyalgo.cfg', instrument=instrument, bar_length='10s', momentum=6, units=10000)
mt.stream_data(mt.instrument, stop=500)
Finally, close out the final position:
00 = mt.create_order(instrument, units=-mt.positon * mt.units, ret=True, suppress=True)
Retrieving account information
api.get_accunt_summary()
api.get_transactions(tid=int(oo['id']) - 2)
api.print_transactions(tid=int(oo['id']) - 18)









