Использование машинного обучения для создания торговой стратегии
Поблагодарить за перевод, можно подписавшись на канал Crypto_Track
Используйте Python и chatGPT для построения инновационных торговых стратегий
Мы хотим использовать машинное обучение для извлечения информации о будущих изменениях цены Bitcoin из данных о финансировании и объеме торгов, а также разработать прибыльную торговую стратегию.
Для этого мы будем использовать Python, sklearn и chatGPT. Код доступен на моем github.
Мы начнем с импорта всех соотвествующих модулей.
import pandas as pd import matplotlib.pyplot as plt from plotly.subplots import make_subplots import plotly.graph_objects as go import plotly.io as pio import plotly.offline as pyo from sklearn.tree import DecisionTreeClassifier from sklearn import tree import graphviz
Мы импортируем цену и данные о финансировании из файла 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']
gain = pd.Series([1 if val > 0 else 0 for val in df.returns])
Мы используем библиотеку sklearn для применения метода машинного обучения с использованием дерева решений. Для данной цели выбираем объем, ставку финансирования и дельту объема в качестве матрицы характеристик и сохраняем их в датафрейме под названием Х. Наша целевая переменная равна 1, если данный текущий период времени дал положительный результат, и 0 в противном случае. Мы применяем разделение данных на обучающую и тестовую выборки в соотношении 80/20 и подгоняем их под дерево решений с максимальной глубиной 3. И последнее, но не менее важное: мы распечатываем и показываем график дерева решений. Этот код был адаптирован из кода, сгенерированного chatGPT, по следующему запросу:
" Как написать код для дерева решений из датафрейма pandas”
# Set the percentage of training data train_data_percentage = 0.5
# Prepare your feature matrix and target variable X = df[['volume', 'algo_funding', 'volume_delta_base_asset']].shift(periods=-1) X = X.drop(X.index[-1]) X = X.drop(X.index[0])
# Target variable y = gain y = y.drop(y.index[-1]) y = y.drop(y.index[0])
# 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:]
# Initialize the decision tree classifier clf = DecisionTreeClassifier(max_depth=3)
# Train the decision tree classifier clf.fit(X_train, y_train)
# Make predictions on the test set y_pred = clf.predict(X_test)
# Visualize the tree structure dot_data = tree.export_graphviz(clf) graph = graphviz.Source(dot_data) graph.render('decision_tree', format='jpeg') graph.view() # Display the visualization
Мы видим, что третий лист слева обладает хорошей прогностической способностью – 70 выборок с положительным результатом из 114 выборок, или около 61%. Поэтому мы реализуем торговую стратегию с параметрами принятия решения, приводящими к этому результату, которые являются:
1. Дельта объема больше, чем -4950,871
2. Ставка финансирования меньше -0,003
Мы вычисляем новый столбец датафрейма, содержащий сигналы на покупку, где 1 означает покупку, а 0 означает отсутствие покупки на текущей свече. Мы предполагаем, что будем удерживать позицию ровно в течение одной свечи, поэтому доходность по одной сделке будет равна цене открытия минус цена закрытия свечи, на которой возникает сигнал. Мы строим данные ohlc на свечном графике с помощью plotly и указываем сигналы на покупку синими стрелками на графике.
df = df[-len(X_test):] df = df.reset_index(drop=True)
weak_buy = lambda row: 1 if (row.algo_funding < -0.003 and row.volume_delta_base_asset > -4950.871) else 0
df['weak_buy'] = df.apply(weak_buy, axis=1).shift(1)
# create subplots with two y-axes fig = make_subplots(specs=[[{"secondary_y": True}]])
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, linewidth=2.5) plt.savefig('equity_curve.png')
Стратегия принесла бы доход в размере 24,39% за данный период времени, указанный в тестовых данных.
Мы можем вычислить следующие показатели производительности:
Mean: 0.04% Standard Deviation: 0.89% Max Drawdown: -22.80% Sharpe Ratio: 3.83 Sortino Ratio: 6.55 Omega Ratio: 1.54
Хотя максимальная просадка более чем на -22,80% может показаться большой, на крипторынках это вовсе не редкость.
Коэффициенты Шарпа и Сортино составляют 3,83 и 6,55, что, несомненно, является выдающимся показателем.
Не забудьте получить код с моего github, и желаю вам счастливой торговли.
Перевод подготовлен каналом Crypto_Track
Ссылка на статью: https://trading-data-analysis.pro/a-decision-tree-machine-learning-based-trading-strategy-returning-280-93-75509a2f6d96