O kNN (k-Nearest Neighbor) é um dos algoritmos mais simples e intuitivos de machine learning. Ele é não paramétrico, ou seja, não faz suposições sobre os dados ou sua distribuição, e pode ser usado para tarefas de classificação ou regressão. O kNN tem aplicações em diversos campos, desde o setor de saúde até o setor financeiro. Neste post, abordaremos um exemplo da utilização do kNN para trading numa tarefa de classificação.
O algoritmo
A intuição por trás do kNN é bem simples. Para cada ponto de dados, o algoritmo encontra as k observações mais próximas e, em seguida, classifica o ponto conforme a classe majoritária. Por exemplo, se k = 3 e se as três observações mais próximas de um ponto de dados específico pertencem às classes A, B e A, respectivamente, o algoritmo classificará o ponto como pertencente à classe A. Normalmente, as k observações mais próximas são definidas como aquelas com a menor distância euclidiana ao ponto de dados em consideração.
kNN para trading - a estratégia
Neste post, a estratégia para usar o kNN para trading consiste em selecionar os k vizinhos mais próximos para fazer uma previsão para um movimento futuro no mercado financeiro. Isso implica que o algoritmo utilizará dados históricos.
Especificamente, utilizaremos as variações nos preços de ações num intervalo de k dias para prever se elas irão subir ou descer na data futura. Se a previsão indicar que elas subirão, iremos comprar ações. Se elas irão descer na nossa previsão, o movimento escolhido será vendê-las. Essa estrategia foi inspirada daqui e daqui.
Portanto, em termos de algoritmo de machine learning, as variações nos preços serão nossas variáveis independentes X e o ato de comprar ou vender serão nossas variáveis dependentes Y. O kNN será usado para prever se, numa data futura, devemos comprar ou vender ações.
Bibliotecas
Utilizaremos as seguintes bibliotecas: pandas, NumPy, scikit-learn, matplotlib e yfinance.
As bibliotecas NumPy e pandas serão utilizadas para fazer parte da manipulação e pré-processamento dos dados. Matplotlib será usado para visualizações. Evidentemente, scikit-learn tem múltiplas funções nesse post e participará do pré-processamento, da computação do kNN e da análise de seus resultados. Já a biblioteca yfinance será utilizada para obter os dados.
Após as instalações, num arquivo Python que pode se chamar knn_trading.py faça as importações necessárias como mostrado abaixo:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
import yfinance as yf
Obtenção dos dados
O kNN é um algoritmo de machine learning. Consequentemente, seu uso segue os passos envolvidos na implementação de qualquer modelo de machine learning descritos aqui e aqui. Portanto, o primeiro passo para utilizá-lo é obter os dados históricos brutos do mercado. Usaremos os dados históricos da Google coletados a partir de 2018.
google_data = yf.download('GOOGL', start='2018-1-1', end='2023-11-27', auto_adjust=True)
Seleção de recursos
Recursos, também chamados de atributos, são as características dos dados brutos que selecionamos para usar como variáveis independentes num algoritmo de machine learning. Utilizaremos os valores de abertura (Open) e fechamento (Close) das ações e também os valores máximos (High) e mínimos (Low).
df = google_data[['Open', 'High', 'Low', 'Close']]
Engenharia de recursos
Em seguida, faremos uma pequena engenharia de recursos. Engenharia de recursos se refere ao processo de criar atributos por meio de transformações nos atributos previamente selecionados. No nosso caso, ao invés de usarmos os atributos selecionados acima como variáveis independentes (Open, Close, High, Low), utilizaremos a variação de preços entre a abertura e fechamento (Open-Close) e a diferença entre o maior e menor valor (High-Low).
df['Open-Close'] = df.Open - df.Close
df['High-Low'] = df.High - df.Low
Pré-processamento
O primeiro pré-processamento que faremos será a remoção de dados faltantes.
df = df.dropna()
O conjunto de dados após essa transformação será nomeado X, terminologia comum para se referir ao conjunto de dados contendo as variáveis independentes em machine learning.
X = df[['Open-Close', 'High-Low']]
Depois, visualizaremos os atributos criados por meio de um gráfico.
ax = plt.subplot(211)
plt.plot(df['Open-Close'], color='r',label='Open-Close')
ax.set_xlabel('Year')
ax.set_ylabel('Open-Close')
ax = plt.subplot(212)
plt.plot(df['High-Low'], color='lightskyblue')
ax.set_xlabel('Year')
ax.set_ylabel('High-Low')
plt.show()
Esses são os atributos que serão usados no treinamento do algoritmo.
Criação do conjunto Y
Y é o conjunto que contém as variáveis dependentes do algoritmo. No nosso caso, ele terá duas classes. A classe 1 significa comprar ações e a classe -1 significa vender. O comando abaixo especifica que, quando o preço de fechamento de uma data é maior do que o da data anterior, a ação correta é comprar (1). Caso contrário, a ação é vender (-1).
Y = np.where(df['Close'].shift(-1) > df['Close'], 1, -1)
Conjunto de treino e teste
A implementação de algoritmos de machine learning tipicamente envolve uma fase de treinamento e depois uma fase de teste. Para isso, geralmente os dados totais disponíveis são divididos em um conjunto de treino (train) e outro de teste (test). O conjunto de treino tipicamente contém 70-80% do total de dados disponíveis. No nosso caso, usaremos 70% e o restante será utilizado para teste.
split = int(0.7*len(df))
X_train, X_test = X[:split], X[split:]
Y_train, Y_test = Y[:split], Y[split:]
kNN com scikit-learn
A fase de implementação do algoritmo em si é super simples, pois utilizaremos a excelente biblioteca scikit-learn. Usaremos uma pipeline que, antes de aplicar o algoritmo, executa mais um pré-processamento sobre os dados: uma normalização. Depois, o algoritmo é aplicado. Note que selecionamos como k os 11 vizinhos mais próximos, mas esse número pode ser variado para ajustar o desempenho do modelo.
knn = Pipeline(
steps=[("scaler", StandardScaler()), ("knn", KNeighborsClassifier(n_neighbors=11))]
)
A implementação de um algoritmo com scikit-learn consiste em selecionar o método que será usado como mostrado acima e depois fazer o treinamento com o comando fit.
knn.fit(X_train, Y_train)
Acurácia
Após o treino, é preciso verificar o desempenho do nosso algoritmo. Utilizaremos sua acurácia para isso.
accuracy_train = round(accuracy_score(Y_train, knn.predict(X_train)), 4)
accuracy_test = round(accuracy_score(Y_test, knn.predict(X_test)), 4)
print(f'Acurácia de Treino: {accuracy_train}')
print(f'Acurácia de Teste: {accuracy_test}')
Os resultados obtidos mostram uma acurácia de 0.62 para os dados de treino e 0.53 para o conjunto de dados de teste.
Acurácia de Treino: 0.6295
Acurácia de Teste: 0.5314
Com esses resultados, o próximo passo é aprimorar o desempenho do algoritmo criando pipelines mais elaboradas, variando o valor de k, etc. Assim que um resultado satisfatório for obtido, é importante fazer backtesting para garantir que o desempenho do modelo é realmente bom antes de utilizá-lo para fazer compras e vendas para valer.
Concluindo
Nesse post, fizemos uma demonstração de como o kNN pode ser usado para trading. Nossa estratégia utilizou uma tarefa simples e intuitiva de classificação para mostrar como esse algoritmo pode ser facilmente usado no mercado financeiro. Existem várias maneiras de alterar o código desenvolvido para obter estratégias mais elaboradas e robustas. Portanto, consulte a documentação da biblioteca scikit-learn para conhecer os outros algoritmos que ela possui e se divirta.