Quantum Trading Brasil
Trading quântico em menos de 100 linhas de código Python
O trading algorítmico refere-se à negociação computadorizada e automatizada de instrumentos financeiros (com base em algum algoritmo ou regra) com pouca ou nenhuma intervenção humana durante as horas de negociação. Quase qualquer tipo de instrumento financeiro - seja ações, moedas, commodities, produtos de crédito ou volatilidade - pode ser negociado dessa maneira.
Não só isso, em certos segmentos de mercado, os algoritmos são responsáveis pela maior parte do volume de negociação. Os livros The Quants, de Scott Patterson, e More Money Than God, de Sebastian Mallaby, pintam uma imagem vívida dos primórdios do trading algorítmico e das personalidades por trás de sua ascensão.
As barreiras à entrada para negociação algorítmica nunca foram menores. Não muito tempo atrás, somente investidores institucionais com orçamentos de TI na casa dos milhões de dólares poderiam participar, mas hoje mesmo indivíduos equipados apenas com um notebook e uma conexão com a Internet podem começar em poucos minutos. Algumas tendências importantes estão por trás deste desenvolvimento:
- Software de código aberto: Todo software que um trader precisa para começar em negociação algorítmica está disponível na forma de código aberto; especificamente, o Python se tornou a linguagem e o ecossistema de escolha.
- Fontes de dados abertas: Mais e mais conjuntos de dados valiosos estão disponíveis em fontes abertas e gratuitas, fornecendo uma variedade de opções para testar hipóteses e estratégias de negociação.
- Plataformas de negociação on-line: há um grande número de plataformas de negociação on-line que fornecem acesso fácil e padronizado a dados históricos (via RESTful APIs) e dados em tempo real (via APIs de transmissão de soquete) e também oferecem recursos de negociação e portfólio (via APIs programáticas).
Este artigo mostra como implementar um projeto de comércio algorítmico completo, desde o backtesting da estratégia até a realização de negociações automatizadas em tempo real. Aqui estão os principais elementos do projeto:
- Estratégia: Eu escolhi uma estratégia de momentum de série temporal (cf. Moskowitz, Tobias, Yao Hua Ooi e Lasse Heje Pedersen (2012): "Momento Momento Temporal". Journal of Financial Economics, Vol. 104, 228-250.), Que basicamente pressupõe que um instrumento financeiro que tenha funcionado bem/mal continuará a fazê-lo.
- Plataforma: Eu escolhi Oanda; Ela permite que você negocie uma variedade de contratos alavancados para diferenças (CFDs), que essencialmente permitem apostas direcionais em um conjunto diversificado de instrumentos financeiros (por exemplo, moedas, índices de ações, commodities).
- Dados: receberemos todos os dados históricos e dados de streaming da Oanda.
- Software: usaremos o Python em combinação com os poderoso pandas da biblioteca de análise de dados, além de alguns pacotes adicionais do Python.
O artigo pressupõe que você tenha uma instalação do Python 3.5 disponível com as principais bibliotecas de análise de dados, como NumPy e Pandas, incluídas. Se não, você deve, por exemplo, baixar e instalar a distribuição do Anaconda Python.
Conta Oanda
Em http://oanda.com, qualquer pessoa pode registrar-se para uma conta de demonstração gratuita ("troca de papel") em poucos minutos. Depois de ter feito isso, para acessar a API do Oanda programaticamente, você precisa instalar o pacote relevante do Python:
pip install oandapy
Para trabalhar com o pacote, você precisa criar um arquivo de configuração com o nome de arquivo oanda.cfg que tenha o seguinte conteúdo:
[oanda]
[oanda]
account_id = YOUR_ACCOUNT_ID
access_token = YOU_ACCESS_TOKE
Substitua as informações acima pelo ID e token que você encontra em sua conta na plataforma Oanda.
In [1]:
import configparser # 1
import oandapy as opy # 2
config = configparser.ConfigParser() # 3
config.read('oanda.cfg') # 4
oanda = opy.API(environment='practice',
access_token=config['oanda']['access_token']) # 5
A execução deste código fornece o objeto principal para trabalhar programaticamente com a plataforma Oanda.
Backtesting
Nós já configuramos tudo o que é necessário para começar com o backtesting da estratégia de momentum. Em particular, somos capazes de recuperar dados históricos da Oanda. O instrumento que usamos é EUR_USD e baseia-se na taxa de câmbio EUR/USD.
A primeira etapa do backtesting é recuperar os dados e convertê-los em um objeto DataFrame do pandas. O conjunto de dados é para os dois dias 8 e 9 de dezembro de 2016 e tem uma granularidade de um minuto. A saída no final do bloco de código a seguir fornece uma visão geral detalhada do conjunto de dados. Ele é usado para implementar o backtesting da estratégia de negociação.
In [2]:
import pandas as pd # 6
data = oanda.get_history(instrument='EUR_USD', # our instrument
start='2016-12-08', # start data
end='2016-12-10', # end date
granularity='M1') # minute bars # 7
df = pd.DataFrame(data['candles']).set_index('time') # 8
df.index = pd.DatetimeIndex(df.index) # 9
df.info() # 10
DatetimeIndex: 2658 entries, 2016-12-08 00:00:00 to 2016-12-09 21:59:00
Data columns (total 10 columns):
closeAsk 2658 non-null float64
closeBid 2658 non-null float64
complete 2658 non-null bool
highAsk 2658 non-null float64
highBid 2658 non-null float64
lowAsk 2658 non-null float64
lowBid 2658 non-null float64
openAsk 2658 non-null float64
openBid 2658 non-null float64
volume 2658 non-null int64
dtypes: bool(1), float64(8), int64(1)
memory usage: 210.3 KB
Em segundo lugar, formalizamos a estratégia de momentum informando ao Python para fazer o retorno médio do log nas últimas barras de 15, 30, 60 e 120 minutos para derivar a posição no instrumento. Por exemplo, o retorno médio do log das últimas barras de 15 minutos fornece o valor médio das últimas 15 observações de retorno. Se esse valor for positivo, nós ficamos/permanecemos longos(comprados) no instrumento negociado; se for negativo, nós ficamos short(vendidos). Para simplificar o código que se segue, apenas confiamos nos valores de closeAsk que recuperamos através do nosso bloco de código anterior:
In [3]:
import numpy as np # 11
df['returns'] = np.log(df['closeAsk'] / df['closeAsk'].shift(1)) # 12
cols = [] # 13
for momentum in [15, 30, 60, 120]: # 14
col = 'position_%s' % momentum # 15
df[col] = np.sign(df['returns'].rolling(momentum).mean()) # 16
cols.append(col) # 17
Terceiro, para obter o desempenho absoluto da estratégia de momentum para os diferentes intervalos de momentum (em minutos), é necessário multiplicar os posicionamentos derivados acima (deslocados em um dia) pelos retornos de mercado. Veja como fazer isso:
In [4]:
%matplotlib inline
import seaborn as sns; sns.set() # 18
strats = ['returns'] # 19
for col in cols: # 20
strat = 'strategy_%s' % col.split('_')[1] # 21
df[strat] = df[col].shift(1) * df['returns'] # 22
strats.append(strat) # 23
df[strats].dropna().cumsum().apply(np.exp).plot() # 24
Out[4]:
A observação do gráfico acima revela que, ao longo do período do conjunto de dados, o instrumento negociado em si tem um desempenho negativo de cerca de -2%. Entre as estratégias de momentum, a baseada em 120 minutos apresenta um desempenho melhor, com um retorno positivo de cerca de 1,5% (ignorando o spread bid / ask). Em princípio, essa estratégia mostra "alfa real": gera um retorno positivo mesmo quando o próprio instrumento mostra um negativo.Trading automatizado
Depois de ter decidido qual estratégia de negociação implementar, você está pronto para automatizar a operação de negociação. Para acelerar as coisas, estou implementando a negociação automatizada com base em doze barras de cinco segundos para a estratégia de momentum de série temporal, em vez de barras de um minuto usadas para backtesting. Uma única classe bastante concisa faz o truque:
In [5]:
class MomentumTrader(opy.Streamer): # 25
def __init__(self, momentum, *args, **kwargs): # 26
opy.Streamer.__init__(self, *args, **kwargs) # 27
self.ticks = 0 # 28
self.position = 0 # 29
self.df = pd.DataFrame() # 30
self.momentum = momentum # 31
self.units = 100000 # 32
def create_order(self, side, units): # 33
order = oanda.create_order(config['oanda']['account_id'],
instrument='EUR_USD', units=units, side=side,
type='market') # 34
print('\n', order) # 35
def on_success(self, data): # 36
self.ticks += 1 # 37
# print(self.ticks, end=', ')
# appends the new tick data to the DataFrame object
self.df = self.df.append(pd.DataFrame(data['tick'],
index=[data['tick']['time']])) # 38
# transforms the time information to a DatetimeIndex object
self.df.index = pd.DatetimeIndex(self.df['time']) # 39
# resamples the data set to a new, homogeneous interval
dfr = self.df.resample('5s').last() # 40
# calculates the log returns
dfr['returns'] = np.log(dfr['ask'] / dfr['ask'].shift(1)) # 41
# derives the positioning according to the momentum strategy
dfr['position'] = np.sign(dfr['returns'].rolling(
self.momentum).mean()) # 42
if dfr['position'].ix[-1] == 1: # 43
# go long
if self.position == 0: # 44
self.create_order('buy', self.units) # 45
elif self.position == -1: # 46
self.create_order('buy', self.units * 2) # 47
self.position = 1 # 48
elif dfr['position'].ix[-1] == -1: # 49
# go short
if self.position == 0: # 50
self.create_order('sell', self.units) # 51
elif self.position == 1: # 52
self.create_order('sell', self.units * 2) # 53
self.position = -1 # 54
if self.ticks == 250: # 55
# close out the position
if self.position == 1: # 56
self.create_order('sell', self.units) # 57
elif self.position == -1: # 58
self.create_order('buy', self.units) # 59
self.disconnect() # 60
O código abaixo permite que a classe MomentumTrader faça o seu trabalho. A negociação automatizada ocorre no momento calculado em 12 intervalos de duração de cinco segundos. A classe automaticamente interrompe a negociação após 250 ticks de dados recebidos. Isso é arbitrário, mas permite uma rápida demonstração da classe MomentumTrader.
In [6]:
mt = MomentumTrader(momentum=12, environment='practice',
access_token=config['oanda']['access_token'])
mt.rates(account_id=config['oanda']['account_id'],
instruments=['DE30_EUR'], ignore_heartbeat=True)
{'price': 1.04858, 'time': '2016-12-15T10:29:31.000000Z', 'tradeReduced': {}, 'tradesClosed': [], 'tradeOpened': {'takeProfit': 0, 'id': 10564874832, 'trailingStop': 0, 'side': 'buy', 'stopLoss': 0, 'units': 100000}, 'instrument': 'EUR_USD'}
{'price': 1.04805, 'time': '2016-12-15T10:29:46.000000Z', 'tradeReduced': {}, 'tradesClosed': [{'side': 'buy', 'id': 10564874832, 'units': 100000}], 'tradeOpened': {'takeProfit': 0, 'id': 10564875194, 'trailingStop': 0, 'side': 'sell', 'stopLoss': 0, 'units': 100000}, 'instrument': 'EUR_USD'}
{'price': 1.04827, 'time': '2016-12-15T10:29:46.000000Z', 'tradeReduced': {}, 'tradesClosed': [{'side': 'sell', 'id': 10564875194, 'units': 100000}], 'tradeOpened': {'takeProfit': 0, 'id': 10564875229, 'trailingStop': 0, 'side': 'buy', 'stopLoss': 0, 'units': 100000}, 'instrument': 'EUR_USD'}
{'price': 1.04806, 'time': '2016-12-15T10:30:08.000000Z', 'tradeReduced': {}, 'tradesClosed': [{'side': 'buy', 'id': 10564875229, 'units': 100000}], 'tradeOpened': {'takeProfit': 0, 'id': 10564876308, 'trailingStop': 0, 'side': 'sell', 'stopLoss': 0, 'units': 100000}, 'instrument': 'EUR_USD'}
{'price': 1.04823, 'time': '2016-12-15T10:30:10.000000Z', 'tradeReduced': {}, 'tradesClosed': [{'side': 'sell', 'id': 10564876308, 'units': 100000}], 'tradeOpened': {'takeProfit': 0, 'id': 10564876466, 'trailingStop': 0, 'side': 'buy', 'stopLoss': 0, 'units': 100000}, 'instrument': 'EUR_USD'}
{'price': 1.04809, 'time': '2016-12-15T10:32:27.000000Z', 'tradeReduced': {}, 'tradesClosed': [{'side': 'buy', 'id': 10564876466, 'units': 100000}], 'tradeOpened': {}, 'instrument': 'EUR_USD'}
A saída acima mostra as negociações individuais executadas pela classe MomentumTrader durante uma execução de demonstração. A captura de tela abaixo mostra o aplicativo de área de trabalho fxTradePractice da Oanda, onde uma negociação da execução da classe MomentumTrader em EUR_USD está ativa.
Todas as saídas de exemplo mostradas neste artigo são baseadas em uma conta demo (onde somente papel-moeda é usado em vez de dinheiro real) para simular negociações algorítmicas. Para mudar para uma operação de negociação real com dinheiro real, basta criar uma conta real com a Oanda, fornecer fundos reais e ajustar o ambiente e os parâmetros da conta usados no código. O código em si não precisa ser alterado.
Todas as saídas de exemplo mostradas neste artigo são baseadas em uma conta demo (onde somente papel-moeda é usado em vez de dinheiro real) para simular negociações algorítmicas. Para mudar para uma operação de negociação real com dinheiro real, basta criar uma conta real com a Oanda, fornecer fundos reais e ajustar o ambiente e os parâmetros da conta usados no código. O código em si não precisa ser alterado.
Conclusão
Este artigo mostra que você pode iniciar uma operação de negociação algorítmica básica com menos de 100 linhas de código Python. Em princípio, todas as etapas de tal projeto são ilustradas, como recuperar dados para fins de backtesting, fazer backtesting de uma estratégia de momentum e automatizar a negociação com base em uma especificação de estratégia de momentum. O código apresentado fornece um ponto de partida para explorar muitas direções diferentes: usando estratégias de negociação algorítmicas alternativas, negociando instrumentos alternativos, negociando múltiplos instrumentos de uma vez, etc.
A popularidade do comércio algorítmico é ilustrada pela ascensão de diferentes tipos de plataformas. Por exemplo, a Quantopian - uma plataforma de backtesting baseada na web e baseada em Python para estratégias de negociação algorítmica - informou no final de 2016 que havia atraído uma base de usuários de mais de 100.000 pessoas. Plataformas de negociação on-line como a Oanda ou aquelas para criptomoedas como a Gemini permitem que você comece em mercados reais em poucos minutos e atenda a milhares de traders ativos em todo o mundo.
Fonte: The Pythin Quants
Nenhum comentário:
Postar um comentário