Используйте Python и chatGPT для создания инновационных торговых стратегий

Мы хотим использовать машинное обучение для извлечения информации о будущем движении цены Биткойна из данных о финансировании и различных данных, основанных на объемах, и разработать прибыльную торговую стратегию.

Для этого мы будем использовать Python, tensorflow и chatGPT. Код доступен на моем github.

Начнем с импорта всех соответствующих модулей.

import pandas as pd
import matplotlib.pyplot as plt
import plotly.graph_objects as go
import plotly.io as pio
import numpy as np
from plotly.subplots import make_subplots
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

Мы импортируем данные о цене, объеме и финансировании из CSV-файла и в дополнение к этому вычисляем дельту объема и процентную доходность.

df = pd.read_csv('merged_df.csv')

def _compute_vd_helper(volume: float, taker_buy_volume: float) -> float:
    
    vd = 2*taker_buy_volume - volume
    return vd

df['volume_delta_base_asset'] = df.apply(lambda x: _compute_vd_helper(x.volume,
                                         x.taker_buy_base_asset_volume), axis=1)

df['returns'] = (df.close - df.open)/df.open
df['algo_funding'] = 100 * df['fundingRate']

df['gain'] = pd.Series([1 if val > 0 else 0 for val in df.returns])

Мы подготавливаем наборы данных и нормализуем признаки. Для этой цели мы выбираем несколько наборов данных на основе объема, данных о ставке финансирования и цене в качестве нашей матрицы признаков и сохраняем их во фрейме данных с именем X.Наша целевая переменная равна 1, если текущий период времени дал положительный результат и 0 в противном случае.Мы применяем к нашим данным разделение обучения/тестирования 50/50.Этот код и код в следующем абзаце были адаптированы из chatGPT сгенерированный код с подсказкой:

"Как эта модель дерева решений будет выглядеть как модель lstm?

[код]”

Код метода дерева решений в подсказке был показан в предыдущей статье, и ему также помогло использование chatGPT.

# Set the percentage of training data
train_data_percentage = 0.5

# Prepare your feature matrix and target variable
X = df[['open', 'high', 'low', 'close', 
        'volume', 'quote_asset_volume', 'number of trades',
        'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume',
        'fundingRate', 'volume_delta_base_asset', 'algo_funding']].shift(periods=-1)
X = X.drop(X.index[-1])
X = X.drop(X.index[0])
X = X.values
# X = df[['volume', 'algo_funding', 'volume_delta_base_asset']].values
y = df['gain']
y = y.drop(y.index[-1])
y = y.drop(y.index[0])
y = y.values

# Normalize the features
X = (X - X.mean()) / X.std()

# Split the data into training and testing sets

# Calculate the number of samples for training based on the percentage
num_train_samples = int(train_data_percentage * len(X))

# Split the data into training and testing sets
X_train = X[:num_train_samples]
X_test = X[num_train_samples:]
y_train = y[:num_train_samples]
y_test = y[num_train_samples:]

# Reshape the input data to match LSTM input shape (samples, timesteps, features)
X_train = X_train.reshape(X_train.shape[0], 1, X_train.shape[1])
X_test = X_test.reshape(X_test.shape[0], 1, X_test.shape[1])

Подготавливаем модель со слоями и т.д.

Мы используем библиотеку tensorflow для применения метода машинного обучения с долговременной кратковременной памятью (LSTM).

# Build the LSTM model
model = Sequential()
model.add(LSTM(32, input_shape=(1, X_train.shape[2])))  # 32 is the number of LSTM units
model.add(Dense(64, activation='relu'))  # Additional dense layer
model.add(Dense(128, activation='relu'))  # Additional dense layer
model.add(Dense(256, activation='relu'))  # Additional dense layer
model.add(Dense(512, activation='relu'))  # Additional dense layer
model.add(Dense(1024, activation='relu'))  # Additional dense layer
model.add(Dense(512, activation='relu'))  # Additional dense layer
model.add(Dense(256, activation='relu'))  # Additional dense layer
model.add(Dense(128, activation='relu'))  # Additional dense layer
model.add(Dense(64, activation='relu'))  # Additional dense layer
model.add(Dense(1, activation='sigmoid'))

# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# Train the model
model.fit(X_train, y_train, epochs=100, batch_size=32)

# Make predictions on the test data
y_pred = model.predict(X_test)

# Convert the probabilities to class labels
y_pred_classes = np.round(y_pred).flatten()

# Compare the predicted classes with the true labels
accuracy = np.mean(y_pred_classes == y_test)
print("Test Accuracy:", accuracy)

# Save the trained model
model.save('lstm_model.h5')

Мы добавляем новый столбец в кадр данных, содержащий прогнозы модели LSTM. В этом случае столбец содержит значения 1 и 0, где 1 означает покупку, а 0 означает отсутствие покупки на текущей свече. Мы предполагаем, что будем держать позицию ровно одну свечу, поэтому доход по одной сделке будет равен цене открытия минус цена закрытия свечи, на которой возникает сигнал. Мы отображаем данные ohlc на графике свечей с помощью plotly и обозначаем сигналы покупки синими стрелками на графике.

df = df[-len(X_test):]
df = df.reset_index(drop=True)

# create subplots with two y-axes
fig = make_subplots(specs=[[{"secondary_y": True}]])

df['weak_buy'] = y_pred_classes # df.apply(weak_buy, axis=1).shift(1)

fig.add_trace(go.Candlestick(
    x=pd.to_datetime(df['open time'], unit='ms'),
    open=df.open,
    high=df.high,
    low=df.low,
    close=df.close,
    increasing=dict(line=dict(color='green')),
    decreasing=dict(line=dict(color='red')),
    name='Price')
)

fig.add_trace(go.Scatter(
    x=pd.to_datetime(df['open time'][df.weak_buy > 0], unit='ms'),
    y=-3000+df.low[df.weak_buy > 0],
    name='weak buy',
    mode='markers',
    marker=dict(
        symbol='triangle-up',
        size=10,
        color='blue',
        line=dict(width=1, color='blue'),
    )
))

pio.write_image(fig, 'trade_entries_chart.jpeg', format='png')
pyo.plot(fig, filename='plot.html', auto_open=True)

Мы вычисляем кривую капитала нашей стратегии, суммируя доходность всех свечей, где наш алгоритм дал сигнал на покупку. Этот код был адаптирован из сгенерированного кода chatGPT с подсказкой:

«Если у меня есть фрейм данных со столбцом, содержащим сигналы покупки для торговой стратегии, где 1 означает покупку, а 0 означает ничего не делать, а второй столбец содержит процентную доходность за этот период. Как я могу рассчитать кривую капитала этой торговой стратегии в третьем столбце».

# Create a new column for the equity curve
df['equity_curve'] = 1.0  # Initial value of 1.0

# Iterate through the DataFrame rows
for i in range(1, len(df)):
    # Compute equity curve based on buy signals and percentage returns
    if df.weak_buy.iloc[i] == 1:
        df.equity_curve.at[i] = df.equity_curve.iloc[i-1] * (1 + df.returns.iloc[i])
    else:
        df.equity_curve.at[i] = df.equity_curve.iloc[i-1]

# Create a larger figure
plt.figure(figsize=(18, 7))  # Set the width to 8 inches and height to 6 inches
plt.grid(True)
plt.plot(pd.to_datetime(df['open time'], unit='ms'), df.equity_curve*df.close.iloc[0], linewidth=2.5)
plt.plot(pd.to_datetime(df['open time'], unit='ms'), df.close, linewidth=2.5)
plt.savefig('equity_curve_lstm.png')

Стратегия вернула бы 42% за указанный период времени тестовых данных. Мы сравниваем доходность нашей модели по сравнению с простой стратегией «купи и держи».

Чтобы получить лучшее сравнение между нашей стратегией с помощью машинного обучения и простой стратегией «купи и держи», мы можем вычислить и сравнить показатели эффективности стратегии «купи и держи».

Buy and Hold 

Mean:            0.02%
Standard Deviation: 3.27%
Max Drawdown:    -76.70%
Sharpe Ratio:    0.71
Sortino Ratio:   1.01
Omega Ratio:     1.02

с соответствующими показателями модели LSTM,

LSTM Model

Mean:            0.09%
Standard Deviation: 2.69%
Max Drawdown:    -52.20%
Sharpe Ratio:    3.07
Sortino Ratio:   4.63
Omega Ratio:     1.10 

Хотя максимальная просадка более -52% может показаться большой, это вовсе не редкость на криптовалютных рынках и все же значительно меньше -76,7%, понесенных стратегией «купи и держи».

Коэффициенты Шарпа и Сортино с 3,07 и 4,63, несомненно, выдающиеся, а также значительно лучше, чем коэффициенты 0,71 и 1,01 стратегии «купи и держи».

Поскольку модель не является детерминированной, обучение модели заново с помощью предоставленного кода приведет к другому результату. Поэтому вы можете найти точную модель из этой статьи на моем гитхабе вместе с кодом. Чтобы загрузить модель, вы можете использовать этот фрагмент кода:

from tensorflow.keras.models import load_model

# Load the saved model
loaded_model = load_model('lstm_model.h5')

# Use the loaded model for prediction or evaluation
predictions = loaded_model.predict(X_test)

Не забудьте получить код с моего github и удачной торговли.

Если вам нравится читать мои истории и вы хотите поддержать меня, зарегистрируйтесь, чтобы стать Medium Member. Это 5 долларов в месяц, что дает вам неограниченный доступ к тысячам статей только для членов о Python, науке о данных, искусственном интеллекте, машинном обучении, торговле, криптографии и многом другом. Если вы зарегистрируетесь по моей ссылке, я получу небольшую комиссию без каких-либо дополнительных затрат для вас.