MACD

  • Знакомство
  • Алгоритмический сигнал MACD с предупреждающим флагом дивергенции
  • Торговля с MACD и RSI
  • Объединение Williams %R и MACD в Python
  • Реализация MACD в Python

Знакомство

Трендовый осциллятор MACD, или индикатор схождения-расхождения скользящих средних (Moving Average Convergence/Divergence), один из наиболее распространенных классических инструментов технического анализа.
Этот индикатор был разработан известным Нью-Йоркским трейдером Джералдом Аппелем в 1979 году для анализа рынка акций, а после перекочевал и на другие рынки, в частности рынки фьючерсов и валюты. Джеральд Аппель, также является автором ряда книг, таких как «Winning Marker System: 83 ways to beat the market», «Stock market trading systems» «New directions in technical analysis» и других, а также выпускал собственный бюллетень «Systems and Forecasts».

Индикатор MACD является, так называемым, трендовым осциллятором, сочетающим в себе свойства и трендового индикатора, и осциллятора. Рассчитывается MACD на основании скользящих средних. Цель индикатора упростить визуальное восприятие сигналов, подаваемых скользящими средними, снизить запаздывание и убрать ряд недостатков, присущих обычным трендовым индикаторам. Существует два способа построения: линейный MACD и гистограмма MACD.

Для расчета используются три экспоненциальные скользящие средние с разными периодами. Из быстрой скользящей средней с меньшим периодом (ЕМАs) вычитается медленная скользящая средняя с большим периодом (EMAl). По полученным значениям строится линия MACD.

MACD = ЕМАs(P) − EMAl(P)

Периоды по умолчанию выбираются 12 и 26. Далее полученная линия сглаживается третьей экспоненциальной скользящей средней (EМАa), как правило, с периодом 9 и получается, так называемая, сигнальная линия MACD (Signal).

Signal = EМАa(ЕМАs(P) − EMAl(P))

Именно эти две получившиеся кривые представляют из себя обычный линейный MACD. Также в окне индикатора обычно отмечена нулевая линия, относительно которой колеблются кривые.

При построении гистограммы MACD (MACD Histogram), столбики гистограммы показывают разность между линиями Signal и MACD, еще более упрощая восприятие индикатора. Однако, стоит упомянуть, что в некоторых торговых терминалах гистограмма MACD строится несколько по-другому. Столбики гистограммы могут заменять линию MACD, а сигнальная линия остается как есть. Тем не менее, в терминале Quik гистограмма обозначает именно схождение-расхождение линий.

Использование MACD.

Исходя из формулы расчета можно легко определить, что когда быстрая скользящая средняя выше медленной, линия MACD находится выше нуля, а когда наоборот – ниже нуля. Соответственно, положение MACD относительно нулевой отметки и направление её движения говорит о преобладании «бычьей» или «медвежьей» тенденции.

Наиболее эффективен индикатор на рынках с широким спектром колебаний. Хорошие точки входа удается получить при наличии четкого тренда. При этом в узком рэндже MACD будет генерировать намного меньше ложных сигналов, чем прочие трендовые индикаторы, в том числе, обычные скользящие средние. Рекомендуемый для использования таймфрейм от часового и выше.

Настраивать индикатор рекомендуется индивидуально под каждый инструмент. Как и в большинстве случаев, чем ниже настройки, тем больше ложных сигналов подает индикатор, чем выше настройки, тем больше сигналов он пропускает. Сам автор предлагал следующие периоды скользящих средних:

Для продаж: 12 – быстрая, 26 – медленная, 9 — сигнальная

Для покупок: 8 – быстрая, 17 – медленная, 9 – сигнальная

Метод построения скользящей средней по умолчанию используется exponential (экспоненциальный). В quik также доступны следующие типы средних: simple (простая), smoothed (сглаженная), и vol. Adjusted (скорректированная на объем).

Для расчета скользящих средних могут использоваться цены закрытия (close), открытия(open), максимум(high), минимум(low), median = (high+low)/2 и typical = (high+low+close)/3. Рекомендуется использовать close.

Торговля с использованием MACD учитывает следующие сигналы индикатора:

Пересечения линий

Основным сигналом, который подает индикатор, является пересечение линии MACD и сигнальной линии. Когда основная линия MACD пересекает сигнальную снизу-вверх, это сигнал на покупку. Пересечение сверху вниз напротив сигнал для продажи. На гистограмме такой сигнал будет соответствовать переходу столбцов гистограммы через ноль. Особенно хорошо использовать такой сигнал при открытии сделок в направлении тренда на старшем таймфрейме. Выход из сделки осуществляется по противоположному сигналу, либо с использованием других инструментов теханализа.

Использование в качестве осциллятора

Когда цена находится в рэндже и амплитуда колебаний цены достаточна, чтобы соотношение риск/прибыль было удовлетворительным, гистограмму MACD можно использовать для оценки перекупленности или перепроданности торгуемого актива. Когда столбцы находятся выше нуля и после роста появляется первый снижающийся столбец – это можно использовать как вспомогательный сигнал, говорящий о росте давления продавцов. Противоположная ситуация будет указывать на растущее давление покупателей. При этом отклонение гистограммы от нуля должно быть не менее 0,5.

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

Дивергенция

Пожалуй, самый распространенный сигнал MACD, который используется сегодня. Когда цена рисует новый экстремум, а линия MACD показывает противоположную динамику, это свидетельствует о затухании тренда и высокой вероятности движения в противоположную сторону.

Важное правило — дивергенции следует искать вблизи окончания тренда. На откатах или в боковике сигнал не эффективен.

Обычно дивергенция используется на линейном MACD. Есть ряд стратегий, предполагающих использование дивергенции на MACD гистограмме. Это менее распространенный вариант, однако для некоторых активов может оказаться действенным.


Использование в сочетании с другими инструментами теханализа

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

Алгоритмический сигнал MACD с предупреждающим флагом дивергенции

Moving Average Convergence Divergence — популярный и универсальный торговый индикатор, созданный Джеральдом Аппель в конце 1970-х годов. В этой статье мы сосредоточимся на том, как реализовать это алгоритмически. Поступая таким образом, мы можем ввести его в другие наши последующие процессы (например, ансамблевую модель, включающую несколько технических индикаторов и контекст цена/объем, о котором мы писали ранее).

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

Мы будем использовать следующие библиотеки: yfinance для ценовых данных, pandas для организации структуры данных, numpy для манипулирования данными, peakdetect для обнаружения пиковых впадин и matplotlib для визуализации.

import yfinance as yf
import pandas as pd
import numpy as np
from peakdetect import peakdetect
import matplotlib.pyplot as plt

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

def generate_macd (df, start, end=None):

raw_data_df = df.loc[start:end].copy() #In this case, it takes in the output from regime define

exp1 = raw_data_df['Close'].ewm(span=12, adjust=False).mean()
exp2 = raw_data_df['Close'].ewm(span=26, adjust = False).mean()
macd = pd.DataFrame(exp1 - exp2).rename(columns = {'Close':'macd'})
signal = pd.DataFrame(macd.ewm(span=9, adjust = False).mean()).rename(columns = {'macd':'signal'})
hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'})
frames = [raw_data_df, macd, signal, hist]

output_df = pd.concat(frames, join = 'inner', axis = 1)

## MACD cross-over ##
output_df['MACD_signal'] = np.where(output_df['hist'] < 0, -1, 1)

## Detecting the turning points in the MACD histogram ##
peaks = peakdetect(output_df['hist'], lookahead=5) #It takes 5 observations to confirm a peak/trough
higherPeaks = np.array(peaks[0])
lowerPeaks = np.array(peaks[1])

# Append the turning points to the dataframe #
output_df = output_df.reset_index()
macd_hist_trough_date_dict = {}
macd_hist_trough_date_list = []
macd_hist_peak_date_dict = {}
macd_hist_peak_date_list = []
for n in range(len(list(lowerPeaks[:,0]))):
if list(lowerPeaks[:,1])[n] < 0:
output_df.loc[list(lowerPeaks[:,0])[n],'MACD_hist_trough'] = list(lowerPeaks[:,1])[n]
macd_hist_trough_date_list.append(output_df.loc[list(lowerPeaks[:,0])[n],'Date'])
macd_hist_trough_date_dict[output_df.loc[list(lowerPeaks[:,0])[n],'Date']] = list(lowerPeaks[:,1])[n]

for n in range(len(list(higherPeaks[:,0]))):
if list(higherPeaks[:,1])[n] > 0:
output_df.loc[list(higherPeaks[:,0])[n],'MACD_hist_peak'] = list(higherPeaks[:,1])[n]
macd_hist_peak_date_list.append(output_df.loc[list(higherPeaks[:,0])[n],'Date'])
macd_hist_peak_date_dict[output_df.loc[list(higherPeaks[:,0])[n],'Date']]= list(higherPeaks[:,1])[n]

output_df = output_df.set_index(['Date'])

## Detecting divergence in share price vs. MACD histogram peak/trough ##
output_df['Bearish_divergence'] = np.nan
output_df['Bullish_divergence'] = np.nan

# Bearish divergence #
for n in range (1, len(macd_hist_peak_date_list)): #Bearish divergence if MACD hist value of n is lower than n-1, and price of n is higher than n-1
if (macd_hist_peak_date_dict[macd_hist_peak_date_list[n]] < macd_hist_peak_date_dict[macd_hist_peak_date_list[n-1]]) & (output_df.loc[macd_hist_peak_date_list[n].strftime('%Y-%m-%d'), 'Close'] > output_df.loc[macd_hist_peak_date_list[n-1].strftime('%Y-%m-%d'), 'Close']):
output_df.loc[macd_hist_peak_date_list[n].strftime('%Y-%m-%d'), 'Bearish_divergence'] = -1
# Bullish divergence #
for n in range (1, len(macd_hist_trough_date_list)): #Bullish divergence if MACD hist value of n is higher than n-1, and price of n is lower than n-1
if (macd_hist_trough_date_dict[macd_hist_trough_date_list[n]] > macd_hist_trough_date_dict[macd_hist_trough_date_list[n-1]]) & (output_df.loc[macd_hist_trough_date_list[n].strftime('%Y-%m-%d'), 'Close'] < output_df.loc[macd_hist_trough_date_list[n-1].strftime('%Y-%m-%d'), 'Close']):
output_df.loc[macd_hist_trough_date_list[n].strftime('%Y-%m-%d'), 'Bullish_divergence'] = 1

output_df['Bearish_divergence'].fillna(method='ffill', limit=20, inplace=True)
output_df['Bearish_divergence'].fillna(value=0, inplace=True)
output_df['Bullish_divergence'].fillna(method='ffill', limit=20, inplace=True)
output_df['Bullish_divergence'].fillna(value=0, inplace=True)

# Combining bearish and bullish divergence into a single forward looking signal #
output_df['Divergence_signal'] = output_df['Bearish_divergence'] + output_df['Bullish_divergence']

return output_df

Ниже мы представляем код для функции оценки производительности, которую мы используем. Эта функция предполагает стоимость односторонней транзакции в размере 0,25% и имитирует исполнение сделки через день после изменения сигнала. Предполагается, что сделка торгуется по средней цене открытия, максимума, минимума и закрытия следующего дня. Для оценки производительности в течение рассматриваемого периода мы использовали геометрическую кумулятивную доходность, чтобы отразить сложную природу производительности. Практикующий специалист может пожелать скорректировать это предположение, если он / она предпочитает оценивать сделки по-разному / равномерно.

### Performance evaluation function which we will utilize ###
def performance_evaluation (df, transaction_cost=0.0025): #Assumes transaction cost of 0.25% each way
eval_df = df.copy()
signal_list = list(eval_df.columns)

# We define Average_px as the average of Open, High, Low, Close to approximate a potential execution price
eval_df['Average_px'] = list(eval_df[['Open','High','Low','Close']].mean(axis='columns'))

temp_list = []
for signal in [n for n in signal_list if n not in ['Open', 'High', 'Low', 'Close']]:
# If signal changes, then effective price for the day is the Average_px of next trading day, otherwise use Close price
# This stimulates the trader executing the trade the next day after receiving signal
eval_df['Bm_Effective_'+signal] = np.where(eval_df[signal].shift(1) != eval_df[signal],
eval_df['Average_px'].shift(-1), eval_df['Close'])

# If signal changes, then daily performance is 1.00*(1-(transaction_cost*2)), this represents the transaction
# Performance only accrue the next day, if signal is -1 then it is a short, if signal is +1 then it is a long
eval_df['Performance_'+signal.split('_')[0]] = np.where(eval_df[signal].shift(1) != eval_df[signal], 1.00*(1-(transaction_cost*2)),
np.where(eval_df[signal]==-1, eval_df['Bm_Effective_'+signal].shift(1)/eval_df['Bm_Effective_'+signal],
np.where(eval_df[signal]==1, eval_df['Bm_Effective_'+signal]/eval_df['Bm_Effective_'+signal].shift(1),1)))
eval_df.loc[eval_df.index[0], 'Performance_'+signal.split('_')[0]] = 1
temp_list.append('Performance_'+signal.split('_')[0])

return eval_df[temp_list].cumprod() # Here we represent geometric cumulative performance

Как пользоваться функцией и визуализировать ее вывод

Во-первых, мы вызываем функцию yf.download из библиотеки yfinance, чтобы загрузить данные о ценах для нашего анализа. «mask_start» — это дата начала, с которой наша визуализация начнется позже; Мы назвали его так, потому что мы будем использовать технику маскировки, чтобы скрыть данные от дат, к которым модель в противном случае не имела бы доступа исторически, тем самым предотвращая предвзятость прогноза. «Начальная» дата должна быть установлена на значительную продолжительность перед «mask_start», чтобы дать модели некоторые исходные данные для работы.

Шаг 2 — это код для предотвращения смещения прогноза. Сначала мы создаем список дат, который начинается с «mask_start» до конца периода (в данном случае end = None, поэтому наш код соответствующим образом разрезает кадр данных pandas. Затем мы используем цикл for, чтобы перебрать этот список дат, подвергая функцию, с помощью которой мы генерируем сигнал MACD, данным, которые были бы доступны только в каждый исторический момент времени.

Шаг 3 генерирует выходной кадр данных, к которому мы добавляем столбец торговых сигналов из итеративного процесса на шаге 2. Шаг 4 — это просто функция для оценки совокупной геометрической торговой эффективности с начала «mask_start», а шаг 5 — это визуализация наших результатов.

ticker = 'QQQ' #Change this to ticker of interest, yfinance syntax
start = '2021-01-01'
mask_start = '2022-01-01' #Visuals will display signals from this date onward
end = None

### Step 1: Calling the ticker from yfinance to obtain the data ###
raw_data_df = round(yf.download(tickers=ticker, start=start, end=end,interval = "1d",
group_by = 'column',auto_adjust = True, prepost = True,
treads = True, proxy = None),2)

### Step 2: Slicing and looping to prevent look ahead bias ###
date_list = list(raw_data_df.loc[mask_start:end].index) #Extract list of dates for signals period
trading_signals_list = [generate_macd(raw_data_df, start=start, end=dt)['MACD_signal'].iat[-1].item() for dt in date_list] #Loop to prevent forward bias

### Step 3: Generating the output_df which we will subsequently visualize ###
output_df = generate_macd(raw_data_df, start=mask_start)
output_df['Trade_Signal_MACD'] = trading_signals_list #Append the list of trading signals without look ahead bias to output_df

### Step 4: Calling the performance evaluation function to examine performance ###
# See the function code in the section above, assumes 0.25% transaction cost per way
performance_df = performance_evaluation(output_df[['Open', 'High', 'Low', 'Close', 'Trade_Signal_MACD']])

### Step 5: Visualization ###
fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(40,40), sharex='all')
font = {'family': 'serif',
'weight': 'bold',
'size': 30,
}

## The top subplot ##
output_df[['Close', 'Divergence_signal', 'Trade_Signal_MACD']].plot(style=['grey','#939B62','salmon'], ax=axes[0],
secondary_y=['Divergence_signal','Trade_Signal_MACD'])
axes[0].set_title(f"{str.upper(ticker)}: MACD and divergence signal (momentum-indicator)", fontdict=font)

## The middle subplot ##
output_df[['macd', 'signal', 'MACD_hist_trough', 'MACD_hist_peak']].plot(style=['grey','skyblue', 'ko', 'ro'], ax=axes[1],
title = f"{str.upper(ticker)}: MACD histogram")
for i in range(len(output_df['Close'])):
if str(output_df['hist'][i])[0] == '-':
axes[1].bar(output_df['Close'].index[i], output_df['hist'][i], color = '#ef5350')
else:
axes[1].bar(output_df['Close'].index[i], output_df['hist'][i], color = '#26a69a')

axes[1].set_title(f"{str.upper(ticker)}: MACD histogram", fontdict=font)

## The bottom subplot ##
performance_df.plot(ax=axes[2]);
axes[2].set_title(f"{str.upper(ticker)}: Performance of MACD signal", fontdict=font)

for ax in axes:
ax.tick_params(axis='x', labelsize=30)
ax.tick_params(axis='y', labelsize=30)

На верхнем подграфике показан торговый сигнал MACD (в лососевом красном цвете), из которых +1 указывает на длинную сделку, а -1 — на короткую сделку. Линия, выделенная зеленым цветом, представляет собой предупреждающий флаг дивергенции, который мигает -1, когда более высокие движения цены закрытия не сопровождаются более высокими максимумами на гистограмме MACD, которая визуализирует различия между линией MACD и ее сигнальной линией. По общему признанию, нам было трудно надежно использовать этот сигнал дивергенции сам по себе из-за непоследовательного временного лага от активации сигнала до момента, когда фактически происходит перегиб цены; Тем не менее, он дополняет индикатор импульса, отмечая потенциальные зоны перегиба впереди.

Объяснение реализации MACD с флагом дивергенции

MACD состоит из трех элементов: линии MACD, сигнальной линии и гистограммы. Линия MACD рассчитывается путем вычитания долгосрочной скользящей средней из краткосрочной экспоненциальной скользящей средней. В нашем коде мы используем 12-дневные и 26-дневные экспоненциально-взвешенные средние (EWM). Сигнальная линия определяется как 9-дневная EWM линии MACD. Гистограмма получается путем вычитания сигнальной линии из линии MACD.

exp1 = raw_data_df['Close'].ewm(span=12, adjust=False).mean()
exp2 = raw_data_df['Close'].ewm(span=26, adjust = False).mean()
macd = pd.DataFrame(exp1 - exp2).rename(columns = {'Close':'macd'})
signal = pd.DataFrame(macd.ewm(span=9, adjust = False).mean()).rename(columns = {'macd':'signal'})
hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'})

Мы используем библиотеку peakDetect для определения поворотных точек на гистограмме MACD (мы использовали 5 наблюдений, чтобы подтвердить, что пик или впадина действительно имели место). Коды здесь идентифицируют даты с пиками и впадинами, впоследствии извлекая значения точек на эти даты.

## Detecting the turning points in the MACD histogram ##
peaks = peakdetect(output_df['hist'], lookahead=5) #It takes 5 observations to confirm a peak/trough
higherPeaks = np.array(peaks[0])
lowerPeaks = np.array(peaks[1])

# Append the turning points to the dataframe #
output_df = output_df.reset_index()
macd_hist_trough_date_dict = {}
macd_hist_trough_date_list = []
macd_hist_peak_date_dict = {}
macd_hist_peak_date_list = []
for n in range(len(list(lowerPeaks[:,0]))):
if list(lowerPeaks[:,1])[n] < 0:
output_df.loc[list(lowerPeaks[:,0])[n],'MACD_hist_trough'] = list(lowerPeaks[:,1])[n]
macd_hist_trough_date_list.append(output_df.loc[list(lowerPeaks[:,0])[n],'Date'])
macd_hist_trough_date_dict[output_df.loc[list(lowerPeaks[:,0])[n],'Date']] = list(lowerPeaks[:,1])[n]

for n in range(len(list(higherPeaks[:,0]))):
if list(higherPeaks[:,1])[n] > 0:
output_df.loc[list(higherPeaks[:,0])[n],'MACD_hist_peak'] = list(higherPeaks[:,1])[n]
macd_hist_peak_date_list.append(output_df.loc[list(higherPeaks[:,0])[n],'Date'])
macd_hist_peak_date_dict[output_df.loc[list(higherPeaks[:,0])[n],'Date']]= list(higherPeaks[:,1])[n]

output_df = output_df.set_index(['Date'])

Наконец, приведенный ниже блок кода создает зеленую линию на верхнем подграфике, показанном ранее.

## Detecting divergence in share price vs. MACD histogram peak/trough ##
output_df['Bearish_divergence'] = np.nan
output_df['Bullish_divergence'] = np.nan

# Bearish divergence #
for n in range (1, len(macd_hist_peak_date_list)): #Bearish divergence if MACD hist value of n is lower than n-1, and price of n is higher than n-1
if (macd_hist_peak_date_dict[macd_hist_peak_date_list[n]] < macd_hist_peak_date_dict[macd_hist_peak_date_list[n-1]]) & (output_df.loc[macd_hist_peak_date_list[n].strftime('%Y-%m-%d'), 'Close'] > output_df.loc[macd_hist_peak_date_list[n-1].strftime('%Y-%m-%d'), 'Close']):
output_df.loc[macd_hist_peak_date_list[n].strftime('%Y-%m-%d'), 'Bearish_divergence'] = -1
# Bullish divergence #
for n in range (1, len(macd_hist_trough_date_list)): #Bullish divergence if MACD hist value of n is higher than n-1, and price of n is lower than n-1
if (macd_hist_trough_date_dict[macd_hist_trough_date_list[n]] > macd_hist_trough_date_dict[macd_hist_trough_date_list[n-1]]) & (output_df.loc[macd_hist_trough_date_list[n].strftime('%Y-%m-%d'), 'Close'] < output_df.loc[macd_hist_trough_date_list[n-1].strftime('%Y-%m-%d'), 'Close']):
output_df.loc[macd_hist_trough_date_list[n].strftime('%Y-%m-%d'), 'Bullish_divergence'] = 1

output_df['Bearish_divergence'].fillna(method='ffill', limit=20, inplace=True)
output_df['Bearish_divergence'].fillna(value=0, inplace=True)
output_df['Bullish_divergence'].fillna(method='ffill', limit=20, inplace=True)
output_df['Bullish_divergence'].fillna(value=0, inplace=True)

# Combining bearish and bullish divergence into a single forward looking signal #
output_df['Divergence_signal'] = output_df['Bearish_divergence'] + output_df['Bullish_divergence']

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

Торговля с MACD и RSI

 

 

  1. Установка и настройка
  2. Введение в индикаторы тренда и моментума.
  3. Генерация торговых сигналов
  4. Сюжет Точки входа/выхода
  5. Интерпретация графиков

Установка и настройка

Я предполагаю, что у большинства людей уже есть настройка Python, но если вы новичок в программировании, перейдите к документации и подготовьте свой компьютер, прежде чем продолжить.

Для тех из вас, кто использовал Python и знаком с настройкой, вы можете просто импортировать перечисленные ниже библиотеки и перейти к сути этой статьи.

pip install yfinance

Ссылка ниже отлично справляется с перечислением шагов по использованию библиотеки yfinance. (https://algotrading101.com/learn/yfinance-guide/).

Введение в импульсную торговлю:

Существует 4 основных типа технических индикаторов, используемых при торговле акциями при отслеживании рынка.

  1. Тенденция
  2. Импульс
  3. Том
  4. Летучесть

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

В этой статье мы рассмотрим конвергенцию-дивергенцию скользящих средних, которая представляет собой индикатор импульса, следующий за трендом, который показывает взаимосвязь между двумя скользящими средними цены ценной бумаги. Мы рассчитываем MACD, вычитая 26-недельную экспоненциальную скользящую среднюю (EMA) из 12-недельного периода EMA.

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

Почему это важно?

  • Важно для понимания того, усиливается или ослабевает бычье или медвежье движение цены.
  • Смотрит на темпы недавних изменений цен, чтобы определить, созрела ли акция для ралли или распродажи.

import pandas as pd
import numpy as np
import yfinance as yf
import pandas_datareader as pdr
import datetime as dt
import matplotlib.pyplot as plt

Начинаем!

Давайте начнем с выбора тикеров, которые мы хотим оценить, используя исторические данные Yahoo Finance, а затем установим дату и время на сегодняшнюю дату.

ticker = 'FB'# Last 3 years closing prices starting from Jan 2, 2018.

now = dt.datetime.now()
startyear = 2018
startmonth = 1
startday = 2
start = dt.datetime(startyear, startmonth, startday)df = pdr.get_data_yahoo(ticker, start, now)df.tail()

Индекс относительной силы (RSI):

  • Когда RSI превышает горизонтальный контрольный уровень 30, это бычий знак, а когда он опускается ниже горизонтального контрольного уровня 70, это медвежий знак.

## 14_Day RSIdf['Up Move'] = np.nan
df['Down Move'] = np.nan
df['Average Up'] = np.nan
df['Average Down'] = np.nan
# Relative Strength
df['RS'] = np.nan
# Relative Strength Index
df['RSI'] = np.nan## Calculate Up Move & Down Movefor x in range(1, len(df)):
df['Up Move'][x] = 0
df['Down Move'][x] = 0

if df['Adj Close'][x] > df['Adj Close'][x-1]:
df['Up Move'][x] = df['Adj Close'][x] - df['Adj Close'][x-1]

if df['Adj Close'][x] < df['Adj Close'][x-1]:
df['Down Move'][x] = abs(df['Adj Close'][x] - df['Adj Close'][x-1])

## Calculate initial Average Up & Down, RS and RSIdf['Average Up'][14] = df['Up Move'][1:15].mean()
df['Average Down'][14] = df['Down Move'][1:15].mean()
df['RS'][14] = df['Average Up'][14] / df['Average Down'][14]
df['RSI'][14] = 100 - (100/(1+df['RS'][14]))## Calculate rest of Average Up, Average Down, RS, RSIfor x in range(15, len(df)):
df['Average Up'][x] = (df['Average Up'][x-1]*13+df['Up Move'][x])/14
df['Average Down'][x] = (df['Average Down'][x-1]*13+df['Down Move'][x])/14
df['RS'][x] = df['Average Up'][x] / df['Average Down'][x]
df['RSI'][x] = 100 - (100/(1+df['RS'][x]))

  • Вы можете ‘print(df)’, чтобы увидеть DataFrame, он должен выглядеть как длинная таблица с 6 новыми столбцами.

Постройте график RSI и «Цены закрытия»:

## Chart the stock price and RSIplt.style.use('_classic_test')fig, axs = plt.subplots(2, sharex=True, figsize=(13,9))
fig.suptitle('Facebook Stock Price (top) - 14 day RSI (bottom)')axs[0].plot(df['Adj Close'])
axs[1].plot(df['RSI'])
axs[0].grid()
axs[1].grid()

  • Пожалуйста, посетите мой GitHub для получения полного списка потрясающих тем и стилей шрифтов, которые вы можете использовать для своих графиков!

ГЕНЕРАЦИЯ СИГНАЛОВ НА ПОКУПКУ И ПРОДАЖУ:

## Calculate the buy & sell signals
## Initialize the columns that we needdf['Long Tomorrow'] = np.nan
df['Buy Signal'] = np.nan
df['Sell Signal'] = np.nan
df['Buy RSI'] = np.nan
df['Sell RSI'] = np.nan
df['Strategy'] = np.nan## Calculate the buy & sell signalsfor x in range(15, len(df)):

# Calculate "Long Tomorrow" column
if ((df['RSI'][x] <= 40) & (df['RSI'][x-1]>40) ):
df['Long Tomorrow'][x] = True
elif ((df['Long Tomorrow'][x-1] == True) & (df['RSI'][x] <= 70)):
df['Long Tomorrow'][x] = True
else:
df['Long Tomorrow'][x] = False

# Calculate "Buy Signal" column
if ((df['Long Tomorrow'][x] == True) & (df['Long Tomorrow'][x-1] == False)):
df['Buy Signal'][x] = df['Adj Close'][x]
df['Buy RSI'][x] = df['RSI'][x]

# Calculate "Sell Signal" column
if ((df['Long Tomorrow'][x] == False) & (df['Long Tomorrow'][x-1] == True)):
df['Sell Signal'][x] = df['Adj Close'][x]
df['Sell RSI'][x] = df['RSI'][x]

## Calculate strategy performance
df['Strategy'][15] = df['Adj Close'][15]for x in range(16, len(df)):
if df['Long Tomorrow'][x-1] == True:
df['Strategy'][x] = df['Strategy'][x-1]* (df['Adj Close'][x] / df['Adj Close'][x-1])
else:
df['Strategy'][x] = df['Strategy'][x-1]

Выход / Вход:

## Chart the buy/sell signals:plt.style.use('_classic_test')
fig, axs = plt.subplots(2, sharex=True, figsize=(13,9))
fig.suptitle('Stock Price (top) & 14 day RSI (bottom)')## Chart the stock close price & buy/sell signals:axs[0].scatter(df.index, df['Buy Signal'], color = 'green', marker = '^', alpha = 1)
axs[0].scatter(df.index, df['Sell Signal'], color = 'red', marker = 'v', alpha = 1)
axs[0].plot(df['Adj Close'], alpha = 0.8)
axs[0].grid()## Chart RSI & buy/sell signals:axs[1].scatter(df.index, df['Buy RSI'], color = 'green', marker = '^', alpha = 1)
axs[1].scatter(df.index, df['Sell RSI'], color = 'red', marker = 'v', alpha = 1)
axs[1].plot(df['RSI'], alpha = 0.8)
axs[1].grid()

Конвергенция-дивергенция скользящих средних (MACD):

## Calculate the MACD and Signal Line indicators
## Calculate the Short Term Exponential Moving AverageShortEMA = df.Close.ewm(span=12, adjust=False).mean() ## Calculate the Long Term Exponential Moving AverageLongEMA = df.Close.ewm(span=26, adjust=False).mean() ## Calculate the Moving Average Convergence/Divergence (MACD)MACD = ShortEMA - LongEMA## Calcualte the signal line
signal = MACD.ewm(span=9, adjust=False).mean()

График MACD и сигнальная линия:

## Plot the Chartplt.figure(figsize=(14,8))
plt.style.use('classic')plt.plot(df.index, MACD, label='FB MACD', color = 'blue')
plt.plot(df.index, signal, label='Signal Line', color='red')
plt.xticks(rotation=45)
plt.legend(loc='upper left')
plt.show()

Торговые показатели Facebook за 3 года:

## Performance statistics
## Number of tradestrade_count = df['Buy Signal'].count()## Average Profit per/trade:average_profit = ((df['Strategy'][-1] / df['Strategy'][15])**(1/trade_count))-1## Number of days per/tradetotal_days = df['Long Tomorrow'].count()
average_days = int(total_days / trade_count)print('Strategy yielded ', trade_count, ' trades')
print('Average trade lasted ', average_days, ' days per trade')
print('Our average profit per trade was ', average_profit*100, '%')

Объединение Williams %R и MACD в Python

Подробное тематическое исследование по использованию python для объединения двух технических индикаторов и создания убийственной торговой стратегии

 

Технические индикаторы являются новым явлением на торговой арене, и стоит потратить время на их изучение. Несмотря на то, что он имеет больший потенциал при анализе рынка, обязательно следует учитывать и его недостатки. Их не так много, но одна заметная загвоздка заключается в том, что он выявляет ложные сигналы, которые могут привести к катастрофическим результатам. Таких сигналов трудно избежать, но они не неизбежны, и один из лучших способов сделать это — объединить два технических индикатора, где один индикатор действует как фильтр, который классифицирует подлинные сигналы от ложных. Это именно то, что мы собираемся сделать сегодня.

В этой статье мы собираемся объединить два мощных технических индикатора: Williams %R и Moving Average Convergence/Divergence (MACD), чтобы создать убийственную торговую стратегию, которая максимально искореняет ложные торговые сигналы и существенно повышает доходность инвестиций. Без лишних слов, давайте погрузимся в статью.

Прежде чем двигаться дальше, если вы хотите протестировать свои торговые стратегии без какого-либо кодирования, для этого есть решение. Это BacktestZone. Это платформа для бесплатного тестирования любого количества торговых стратегий на различных типах торгуемых активов без кодирования. Вы можете использовать инструмент прямо сейчас, используя ссылку здесь: https://www.backtestzone.com/

Williams %R

Основанный Ларри Уильямсом, Williams %R представляет собой индикатор импульса, значения которого колеблются от 0 до -100. Этот индикатор больше всего похож на стохастический осциллятор, но отличается своим расчетом. Трейдеры используют этот индикатор для определения потенциальных точек входа и выхода из сделок, строя два уровня перекупленности и перепроданности. Прежде чем перейти к словам об уровнях перекупленности и перепроданности: акция считается перекупленной, когда рыночный тренд кажется чрезвычайно бычьим и обязательно консолидируется. Точно так же акция достигает области перепроданности, когда рыночный тренд кажется чрезвычайно медвежьим и имеет тенденцию к отскоку. Традиционными пороговыми значениями для уровней перекупленности и перепроданности являются 20 и 80 соответственно, но запретов на взятие и других значений нет.

Чтобы рассчитать значения Williams %R с традиционной установкой 14 в качестве периода ретроспективного анализа, сначала определяется самый высокий максимум и самый низкий минимум для каждого периода в течение четырнадцатидневного таймфрейма. Затем берутся две разницы: цена закрытия от самого высокого максимума и самый низкий минимум от самого высокого максимума. Наконец, первая разность делится на вторую разность и кратна -100, чтобы получить значения Вильямса %R. Математически расчет можно представить следующим образом:

W%R 14 = [ H.HIGH - C.PRICE ] / [ L.LOW - C.PRICE ] * ( - 100 )where,
W%R 14 = 14-day Williams %R of the stock
H.HIGH = 14-day Highest High of the stock
L.LOW = 14-day Lowest Low of the stock
C.PRICE = Closing price of the stock

Основная идея этого индикатора заключается в том, что акции будут продолжать достигать новых максимумов, когда это сильный восходящий тренд, и точно так же акции будут достигать новых минимумов, когда они следуют за устойчивым нисходящим трендом. Теперь давайте проанализируем график Williams %R, чтобы получить четкое представление об индикаторе.

Приведенный выше график разделен на две панели: верхняя панель с ценой закрытия данных по акциям Apple и нижняя панель со значениями 14-дневных показаний Apple Williams %R. Теперь диаграмму можно использовать двумя способами. Первый способ заключается в использовании графика в качестве инструмента для определения состояний перекупленности и перепроданности рынка. Вы можете заметить, что над и под рынком построены две горизонтальные серые линии, которые представляют собой не что иное, как уровни перекупленности и перепроданности, построенные на пороге -20 и -80 соответственно. Вы можете считать, что рынок находится в состоянии перекупленности, если Williams %R имеет показания выше верхней линии или линии перекупленности. Точно так же вы можете предположить, что рынок находится в состоянии перепроданности, если Williams %R имеет значение ниже нижней линии или линии перепроданности.

Второй способ использования Williams %R заключается в выявлении ложного импульса на рынке. Во время устойчивого восходящего тренда показания Williams% R, как правило, часто превышают -20. Если индикатор падает и изо всех сил пытается подняться выше -20 перед следующим падением, это указывает на то, что импульс рынка не является подлинным и можно следовать огромному нисходящему тренду. Аналогичным образом, во время здорового нисходящего тренда показания Williams %R часто опускаются ниже -80. Если индикатор растет и не достигает -80 до следующего подъема, это говорит о том, что рынок будет следовать положительной тенденции.

Поскольку Williams %R является индикатором направления (индикатором, движение которого прямо пропорционально движению реального рынка), трейдеры также используют этот индикатор для поиска и подтверждения сильных восходящих или нисходящих трендов на рынке и торговли вместе с ним. Некоторые индикаторы не очень полезны при использовании для выявления или подтверждения рыночных тенденций, поскольку они могут быть запаздывающими по своей природе (индикатор, который учитывает исторические данные для определения текущего значения), но Williams %R является эффективным, потому что это опережающий индикатор (индикатор, который учитывает предыдущие точки данных для прогнозирования будущих движений).

MACD

Прежде чем перейти к MACD, важно знать, что означает экспоненциальная скользящая средняя (EMA). EMA — это тип скользящей средней (MA), которая автоматически присваивает больший вес (ничего, кроме важности) самой последней точке данных и меньший вес точкам данных в далеком прошлом. Например, вопросник будет состоять из 10% вопросов с одной оценкой, 40% вопросов с тремя оценками и 50% вопросов с длинными ответами. Из этого примера вы можете заметить, что мы присваиваем уникальные веса каждому разделу вопросника в зависимости от уровня важности (вероятно, вопросы с длинными ответами придают большее значение, чем вопросы с одной оценкой).

Теперь MACD — это опережающий индикатор, следующий за трендом, который рассчитывается путем вычитания двух экспоненциальных скользящих средних (одна с более длинными, а другая с более короткими периодами). В индикаторе MACD есть три примечательных компонента.

  • Линия MACD: Эта линия представляет собой разницу между двумя заданными экспоненциальными скользящими средними. Для расчета линии MACD рассчитывается одна EMA с более длительным периодом, известная как медленная длина, и другая EMA с более коротким периодом, известная как быстрая длина. Самая популярная длина быстрой и медленной — 12, 26 соответственно. Окончательные значения линий MACD можно получить, вычитая EMA с медленной длиной из EMA с быстрой длиной. Формулу для расчета линии MACD можно представить следующим образом:

MACD LINE = FAST LENGTH EMA - SLOW LENGTH EMA

  • Сигнальная линия: Эта линия является экспоненциальной скользящей средней самой линии MACD за определенный период времени. Самый популярный период для расчета сигнальной линии – 9. Поскольку мы усредняем саму линию MACD, сигнальная линия будет более гладкой, чем линия MACD.
  • Гистограмма: Как следует из названия, это гистограмма, специально построенная для того, чтобы показать разницу между линией MACD и сигнальной линией. Это отличный компонент, который можно использовать для выявления тенденций. Формула для расчета гистограммы может быть представлена следующим образом:

HISTOGRAM = MACD LINE - SIGNAL LINE

Теперь, когда у нас есть понимание того, что такое MACD. Давайте проанализируем график MACD, чтобы построить интуитивное представление об индикаторе.

На этом графике есть две панели: верхняя панель представляет собой график цен закрытия Apple, а нижняя панель представляет собой серию графиков рассчитанных компонентов MACD. Давайте разберемся и посмотрим на каждый компонент.

Первым и наиболее заметным компонентом на нижней панели, очевидно, является график вычисленных значений гистограммы. Вы можете заметить, что график становится красным всякий раз, когда рынок показывает отрицательный тренд, и становится зеленым всякий раз, когда рынок показывает положительную тенденцию. Эта функция графика гистограммы становится очень удобной, когда дело доходит до определения тенденции рынка. График гистограммы распространяется больше, когда разница между линией MACD и сигнальной линией огромна, и заметно, что график гистограммы время от времени сжимается, представляя разницу между двумя другими компонентами, сравнительно меньше.

Следующими двумя компонентами являются линия MACD и сигнальная линия. Линия MACD — это график линии серого цвета, который показывает разницу между EMA с медленной длиной и EMA с быстрой длиной цен на акции Apple. Точно так же график линии синего цвета — это сигнальная линия, которая представляет EMA самой линии MACD. Как мы уже говорили ранее, сигнальная линия кажется более гладкой версией линии MACD, потому что она рассчитывается путем усреднения значений самой линии MACD.

Торговая стратегия

Теперь, когда мы построили некоторые базовые интуитивные представления об индикаторах Williams %R и MACD. Давайте обсудим торговую стратегию, которую мы собираемся реализовать в этой статье. Стратегия довольно проста. Мы открываем длинную позицию (покупаем акции), если предыдущее значение Williams %R выше -50, текущее значение Williams %R ниже -50, а линия MACD больше сигнальной линии. Точно так же мы открываем короткую позицию (продаем акции), если предыдущее значение Williams %R ниже -50, текущее значение Williams %R выше -50, а линия MACD меньше сигнальной линии. Нашу торговую стратегию можно представить следующим образом:

PREV.WR > -50 AND CUR.WR < -50 AND MACD.L > SIGNAL.L ==> BUY SIGNAL
PREV.WR < -50 AND CUR.WR > -50 AND MACD.L < SIGNAL.L ==> SELL SIGNAL

Ну вот! На этом мы завершаем нашу теоретическую часть, и давайте перейдем к части программирования, где мы будем использовать Python, чтобы сначала построить индикаторы с нуля, построить обсуждаемую торговую стратегию, протестировать стратегию на данных акций Apple и, наконец, сравнить результаты с результатами SPY ETF. Давайте займемся кодированием! Прежде чем двигаться дальше, примечание об отказе от ответственности: единственная цель этой статьи — просвещать людей, и ее следует рассматривать как информационный материал, а не как инвестиционный совет или что-то в этом роде.

Реализация на Python

Часть кодирования подразделяется на различные этапы следующим образом:

1. Importing Packages
2. Extracting Stock Data from Twelve Data
3. Williams %R Calculation
4. MACD Calculation
5. Creating the Trading Strategy
6. Creating our Position
7. Backtesting
8. SPY ETF Comparison

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

Шаг 1: Импорт пакетов

Импорт необходимых пакетов в среду python — это шаг, который нельзя пропустить. Первичными пакетами будут Pandas для работы с данными, NumPy для работы с массивами и сложными функциями, Matplotlib для построения графиков и Requests для выполнения вызовов API. Вторичными пакетами будут Math для математических функций и Termcolor для настройки шрифта (необязательно).

Реализация Python:

# IMPORTING PACKAGES

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import requests
from math import floor
from termcolor import colored as cl

plt.style.use('fivethirtyeight')
plt.rcParams['figure.figsize'] = (20,10)

Теперь, когда мы импортировали все необходимые пакеты в наш python. Давайте извлечем исторические данные Apple с помощью конечной точки API Twelve Data.

Шаг 2: Извлечение биржевых данных из двенадцати данных

На этом этапе мы собираемся извлечь исторические данные об акциях Apple, используя конечную точку API, предоставленную twelvedata.com. Перед этим заметка о twelvedata.com: Twelve Data — один из ведущих поставщиков рыночных данных, имеющий огромное количество конечных точек API для всех типов рыночных данных. Очень легко взаимодействовать с API, предоставляемыми Twelve Data, и имеет одну из лучших документаций за всю историю. Кроме того, убедитесь, что у вас есть учетная запись на twelvedata.com, только тогда вы сможете получить доступ к своему ключу API (жизненно важный элемент для извлечения данных с помощью API).

Реализация Python:

# EXTRACTING STOCK DATA

def get_historical_data(symbol, start_date):
api_key = 'YOUR API KEY'
api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}'
raw_df = requests.get(api_url).json()
df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float)
df = df[df.index >= start_date]
df.index = pd.to_datetime(df.index)
return df

aapl = get_historical_data('AAPL', '2010-01-01')
aapl.tail()

Пояснение к коду: Первое, что мы сделали, это определили функцию с именем «get_historical_data», которая принимает символ акции («символ») и дату начала исторических данных («start_date») в качестве параметров. Внутри функции мы определяем ключ API и URL-адрес и сохраняем их в соответствующей переменной. Далее мы извлекаем исторические данные в формате JSON с помощью функции «get» и сохраняем их в переменной «raw_df». После выполнения некоторых процессов по очистке и форматированию необработанных данных JSON мы возвращаем их в виде чистого кадра данных Pandas. Наконец, мы вызываем созданную функцию, чтобы извлечь исторические данные Apple с начала 2010 года и сохранить их в переменной ‘aapl’.

Шаг 3: Расчет %R по Вильямсу

На этом этапе мы собираемся рассчитать значения Williams %R, следуя формуле, которую мы обсуждали ранее.

Реализация Python:

# WILLIAMS %R CALCULATION

def get_wr(high, low, close, lookback):
highh = high.rolling(lookback).max()
lowl = low.rolling(lookback).min()
wr = -100 * ((highh - close) / (highh - lowl))
return wr

aapl['wr_14'] = get_wr(aapl['high'], aapl['low'], aapl['close'], 14)
aapl.tail()

Пояснение к коду: Сначала мы определяем функцию с именем «get_wr», которая принимает в качестве параметров данные о высокой цене акции («high»), данные о низкой цене («low»), данные о цене закрытия («close») и период ретроспективного анализа («период»).

Внутри функции мы сначала определяем самый высокий максимум за определенный период ретроспективного периода с помощью функций «rolling» и «max», предоставляемых пакетом Pandas, и сохраняем его в переменной «highh». Функция «rolling» выполняет то, что она учитывает указанный нами таймфрейм с n-периодом, а функция «max» фильтрует максимальные значения, присутствующие в данном кадре данных.

Затем мы определяем переменную с именем «lowl» для хранения самого низкого минимума за указанный период ретроспективного периода, который мы определили с помощью функций «rolling» и «min» (как следует из названия, фильтрует минимальные значения в данном кадре данных), предоставляемого пакетом Pandas.

Затем мы подставляем определенные максимальные и самые низкие значения в формулу, которую мы обсуждали ранее, чтобы вычислить значения Вильямса %R и сохранить их в переменной ‘wr’. Наконец, мы возвращаемся и вызываем созданную функцию для хранения показаний Apple Williams %R с 14 в качестве периода ретроспективного анализа.

Шаг 4: Расчет MACD

На этом этапе мы собираемся рассчитать все компоненты индикатора MACD из извлеченных исторических данных Apple.

# MACD CALCULATION

def get_macd(price, slow, fast, smooth):
exp1 = price.ewm(span = fast, adjust = False).mean()
exp2 = price.ewm(span = slow, adjust = False).mean()
macd = pd.DataFrame(exp1 - exp2).rename(columns = {'close':'macd'})
signal = pd.DataFrame(macd.ewm(span = smooth, adjust = False).mean()).rename(columns = {'macd':'signal'})
hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'})
return macd, signal, hist

aapl['macd'] = get_macd(aapl['close'], 26, 12, 9)[0]
aapl['macd_signal'] = get_macd(aapl['close'], 26, 12, 9)[1]
aapl['macd_hist'] = get_macd(aapl['close'], 26, 12, 9)[2]
aapl = aapl.dropna()
aapl.tail()

Пояснение к коду: Во-первых, мы определяем функцию с именем «get_macd», которая принимает цену акции («цены»), длину медленной EMA («медленная»), длину быстрой EMA («быстрая») и период сигнальной линии («гладкая»).

Внутри функции мы сначала вычисляем EMA быстрой и медленной длины, используя функцию ‘ewm’, предоставляемую Pandas, и сохраняем их в переменных ’ema1′ и ’ema2′ соответственно.

Затем мы рассчитали значения линии MACD, вычтя EMA медленной длины из EMA быстрой длины и сохранив ее в переменной macd в виде кадра данных Pandas. После этого мы определили переменную с именем «signal» для хранения значений сигнальной линии, рассчитанных путем взятия EMA значений линии MACD («macd») за указанное количество периодов.

Затем мы рассчитали значения гистограммы, вычтя значения линии MACD («macd») из значений сигнальной линии («signal») и сохранив их в переменной hist. Наконец, мы возвращаем все вычисленные значения и вызываем созданную функцию для хранения компонентов MACD от Apple.

Шаг 5: Создание торговой стратегии:

На этом этапе мы собираемся реализовать обсуждаемую комбинированную торговую стратегию Williams %R и Moving Average Convergence/Divergence (MACD) в python.

Реализация Python:

# TRADING STRATEGY

def implement_wr_macd_strategy(prices, wr, macd, macd_signal):
buy_price = []
sell_price = []
wr_macd_signal = []
signal = 0

for i in range(len(wr)):
if wr[i-1] > -50 and wr[i] < -50 and macd[i] > macd_signal[i]:
if signal != 1:
buy_price.append(prices[i])
sell_price.append(np.nan)
signal = 1
wr_macd_signal.append(signal)
else:
buy_price.append(np.nan)
sell_price.append(np.nan)
wr_macd_signal.append(0)

elif wr[i-1] < -50 and wr[i] > -50 and macd[i] < macd_signal[i]:
if signal != -1:
buy_price.append(np.nan)
sell_price.append(prices[i])
signal = -1
wr_macd_signal.append(signal)
else:
buy_price.append(np.nan)
sell_price.append(np.nan)
wr_macd_signal.append(0)

else:
buy_price.append(np.nan)
sell_price.append(np.nan)
wr_macd_signal.append(0)

return buy_price, sell_price, wr_macd_signal

buy_price, sell_price, wr_macd_signal = implement_wr_macd_strategy(aapl['close'], aapl['wr_14'], aapl['macd'], aapl['macd_signal'])

Пояснение к коду: Во-первых, мы определяем функцию с именем «wr_macd_strategy», которая принимает в качестве параметров цены акций («цены»), показания %R Вильямса («wr»), показания линии MACD («macd») и показания сигнальной линии («macd_signal»).

Внутри функции мы создаем три пустых списка (buy_price, sell_price и wr_macd_signal), в которые будут добавлены значения при создании торговой стратегии.

После этого мы реализуем торговую стратегию через фор-цикл. Внутри for-цикла мы передаем определенные условия, и если условия выполняются, соответствующие значения будут добавлены в пустые списки. Если условие для покупки акций будет выполнено, цена покупки будет добавлена в список «buy_price», а значение сигнала будет добавлено как 1, представляющее покупку акций. Точно так же, если условие продажи акций будет выполнено, цена продажи будет добавлена к списку «sell_price», а значение сигнала будет добавлено как -1, представляющее продажу акции. Наконец, мы возвращаем списки, добавленные со значениями. Затем мы вызываем созданную функцию и сохраняем значения в соответствующих переменных.

Шаг 6: Создание нашей позиции

На этом этапе мы собираемся создать список, в котором будет указано 1, если мы владеем акциями, или 0, если мы не владеем акциями или не держим их.

Реализация Python:

# POSITION

position = []
for i in range(len(wr_macd_signal)):
if wr_macd_signal[i] > 1:
position.append(0)
else:
position.append(1)

for i in range(len(aapl['close'])):
if wr_macd_signal[i] == 1:
position[i] = 1
elif wr_macd_signal[i] == -1:
position[i] = 0
else:
position[i] = position[i-1]

close_price = aapl['close']
wr = aapl['wr_14']
macd_line = aapl['macd']
signal_line = aapl['macd_signal']
wr_macd_signal = pd.DataFrame(wr_macd_signal).rename(columns = {0:'wr_macd_signal'}).set_index(aapl.index)
position = pd.DataFrame(position).rename(columns = {0:'wr_macd_position'}).set_index(aapl.index)

frames = [close_price, wr, macd_line, signal_line, wr_macd_signal, position]
strategy = pd.concat(frames, join = 'inner', axis = 1)

strategy.head()

Пояснение к коду: Во-первых, мы создаем пустой список с именем «позиция». Мы проходим два цикла for, один из которых предназначен для генерации значений для списка «позиция», чтобы они точно соответствовали длине списка «сигналов». Другой цикл for-loop — это тот, который мы используем для генерации фактических значений позиции.

Внутри второго цикла for-цикл мы перебираем значения списка ‘signal’, и добавляются значения списка ‘position’ в зависимости от того, какое условие выполняется. Стоимость позиции остается 1, если мы владеем акциями, или остается 0, если мы продали или не владеем акциями. Наконец, мы делаем некоторые манипуляции с данными, чтобы объединить все созданные списки в один фрейм данных.

Из показанного вывода мы видим, что в первых трех строках наша позиция по акции осталась 1 (поскольку торговый сигнал не изменился), но наша позиция внезапно превратилась в 0, когда мы продали акцию, когда торговый сигнал представляет собой сигнал на покупку (-1). Наша позиция будет оставаться -1 до тех пор, пока не произойдут некоторые изменения в торговом сигнале. Теперь пришло время внедрить некоторые процессы тестирования на истории!

Шаг 7: Тестирование на истории

Прежде чем двигаться дальше, важно знать, что такое тестирование на истории. Тестирование на истории — это процесс проверки того, насколько хорошо наша торговая стратегия работает с данными об акциях. В нашем случае мы собираемся реализовать процесс тестирования на истории для нашей комбинированной торговой стратегии Williams %R и MACD на данных по акциям Apple.

Реализация Python:

# BACKTESTING

aapl_ret = pd.DataFrame(np.diff(aapl['close'])).rename(columns = {0:'returns'})
wr_macd_strategy_ret = []

for i in range(len(aapl_ret)):
try:
returns = aapl_ret['returns'][i] * strategy['wr_macd_position'][i]
wr_macd_strategy_ret.append(returns)
except:
pass

wr_macd_strategy_ret_df = pd.DataFrame(wr_macd_strategy_ret).rename(columns = {0:'wr_macd_returns'})

investment_value = 100000
number_of_stocks = floor(investment_value / aapl['close'][0])
wr_macd_investment_ret = []

for i in range(len(wr_macd_strategy_ret_df['wr_macd_returns'])):
returns = number_of_stocks * wr_macd_strategy_ret_df['wr_macd_returns'][i]
wr_macd_investment_ret.append(returns)

wr_macd_investment_ret_df = pd.DataFrame(wr_macd_investment_ret).rename(columns = {0:'investment_returns'})
total_investment_ret = round(sum(wr_macd_investment_ret_df['investment_returns']), 2)
profit_percentage = floor((total_investment_ret / investment_value) * 100)
print(cl('Profit gained from the W%R MACD strategy by investing $100k in AAPL : {}'.format(total_investment_ret), attrs = ['bold']))
print(cl('Profit percentage of the W%R MACD strategy : {}%'.format(profit_percentage), attrs = ['bold']))

Выпуск:

Profit gained from the W%R MACD strategy by investing $100k in AAPL : 1207459.27
Profit percentage of the W%R MACD strategy : 1207%

Пояснение к коду: Во-первых, мы вычисляем доходность акций Apple, используя функцию «diff», предоставляемую пакетом NumPy, и сохраняем ее в виде кадра данных в переменной «aapl_ret». Затем мы передаем цикл for, чтобы перебрать значения переменной «aapl_ret» для расчета доходности, которую мы получили от нашей торговой стратегии, и эти значения доходности добавляются к списку «wr_macd_strategy_ret». Затем мы преобразуем список «wr_macd_strategy_ret» в кадр данных и сохраняем его в переменной «wr_macd_strategy_ret_df».

Далее идет процесс тестирования на истории. Мы собираемся протестировать нашу стратегию, вложив сто тысяч долларов США в нашу торговую стратегию. Итак, во-первых, мы храним сумму инвестиций в переменной «investment_value». После этого мы рассчитываем количество акций Apple, которые мы можем купить, используя сумму инвестиций. Вы можете заметить, что я использовал функцию «пола», предоставляемую пакетом Math, потому что, деля сумму инвестиций на цену закрытия акций Apple, он выдает выходные данные с десятичными числами. Количество акций должно быть целым, а не десятичным числом. Используя функцию «пол», мы можем вырезать десятичные дроби. Помните, что функция «пол» намного сложнее, чем функция «круглый». Затем мы проходим цикл for, чтобы найти доходность инвестиций, за которой следуют некоторые задачи по манипулированию данными.

Наконец, мы печатаем общую прибыль, которую мы получили, инвестировав сто тысяч в нашу торговую стратегию, и выясняется, что мы получили приблизительную прибыль в размере одного миллиона двухсот тысяч долларов США примерно за десять с половиной лет с процентом прибыли 1207%. Это здорово! Теперь давайте сравним нашу доходность с доходностью SPY ETF (ETF, предназначенный для отслеживания индекса фондового рынка S&P 500).

Шаг 8: Сравнение SPY ETF

Этот шаг не является обязательным, но настоятельно рекомендуется, так как мы можем получить представление о том, насколько хорошо наша торговая стратегия работает по сравнению с эталоном (SPY ETF). На этом этапе мы извлечем данные SPY ETF с помощью созданной нами функции «get_historical_data» и сравним доходность, которую мы получаем от SPY ETF, с доходностью нашей торговой стратегии на Apple.

Возможно, вы заметили, что во всех своих статьях об алгоритмической торговле я сравнивал результаты стратегии не с самим рыночным индексом S&P 500, а с SPY ETF, и это связано с тем, что большинство поставщиков биржевых данных (например, Twelve Data) не предоставляют данные индекса S&P 500. Так что у меня нет другого выбора, кроме как пойти с SPY ETF. Если вам посчастливилось получить данные рыночного индекса S&P 500, рекомендуется использовать их для сравнения, а не какой-либо ETF.

Реализация Python:

# SPY ETF COMPARISON

def get_benchmark(start_date, investment_value):
spy = get_historical_data('SPY', start_date)['close']
benchmark = pd.DataFrame(np.diff(spy)).rename(columns = {0:'benchmark_returns'})

investment_value = investment_value
number_of_stocks = floor(investment_value/spy[0])
benchmark_investment_ret = []

for i in range(len(benchmark['benchmark_returns'])):
returns = number_of_stocks*benchmark['benchmark_returns'][i]
benchmark_investment_ret.append(returns)

benchmark_investment_ret_df = pd.DataFrame(benchmark_investment_ret).rename(columns = {0:'investment_returns'})
return benchmark_investment_ret_df

benchmark = get_benchmark('2010-01-01', 100000)
investment_value = 100000
total_benchmark_investment_ret = round(sum(benchmark['investment_returns']), 2)
benchmark_profit_percentage = floor((total_benchmark_investment_ret/investment_value)*100)
print(cl('Benchmark profit by investing $100k : {}'.format(total_benchmark_investment_ret), attrs = ['bold']))
print(cl('Benchmark Profit percentage : {}%'.format(benchmark_profit_percentage), attrs = ['bold']))
print(cl('W%R MACD Strategy profit is {}% higher than the Benchmark Profit'.format(profit_percentage - benchmark_profit_percentage), attrs = ['bold']))

Выпуск:

Benchmark profit by investing $100k : 288493.39
Benchmark Profit percentage : 288%
W%R MACD Strategy profit is 919% higher than the Benchmark Profit

Пояснение к коду: Код, используемый на этом этапе, почти аналогичен тому, который использовался на предыдущем этапе тестирования на истории, но вместо того, чтобы инвестировать в Apple, мы инвестируем в SPY ETF, не реализуя никаких торговых стратегий. Из результатов мы видим, что наша торговая стратегия превзошла SPY ETF на 919%. Замечательно!

Заключительные мысли!

После огромного процесса разрушения как теории, так и программирования, мы успешно изучили, что такое Williams %R и конвергенция/дивергенция скользящих средних, и построили торговую стратегию, объединив оба этих индикатора с помощью python, который действительно приносит прибыль.

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

Следующий аспект – оценка стратегии. Для тех, кто не знает, что означает оценка в сфере торговли, это процесс извлечения практических выводов из торговой стратегии. В этой статье мы сразу пришли к выводу, что наша стратегия прибыльна, просто тщательно изучив полученную прибыль или прибыль, но необходимо учитывать множество факторов. Таким образом, оценка нашей торговой стратегии помогает нам понять ее еще лучше с помощью более практичных и реалистичных фактов.

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

Причина, по которой эти аспекты не обсуждаются в этой статье, заключается в том, что каждая концепция представляет собой совершенно новую главу в торговом пространстве и не может быть уместна только в небольшом разделе статьи. С учетом сказанного, вы дошли до конца статьи. Если вы забыли следовать какой-либо из частей кодирования, не волнуйтесь. Я предоставил полный исходный код в конце статьи. Надеюсь, вы узнали что-то новое и полезное из этой статьи.

Спонсируется: EOD Historical Data является одним из лидеров на рынке финансовых API, предоставляя широкий спектр API, начиная от базовых, таких как рыночные данные на конец дня, и заканчивая настраиваемыми API, такими как API финансовых новостей и API скринера акций. Все их API разработаны таким образом, чтобы их было легко использовать по своей природе, чтобы новички могли работать с ними без каких-либо препятствий. Я лично использовал API EOD Historical Data, и, по моему опыту, их API подходят как для любителей, так и для профессионалов и используются для сторонних проектов и для создания приложений корпоративного уровня.

Полный код:

# IMPORTING PACKAGES

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import requests
from math import floor
from termcolor import colored as cl

plt.style.use('fivethirtyeight')
plt.rcParams['figure.figsize'] = (20,10)

# EXTRACTING STOCK DATA

def get_historical_data(symbol, start_date):
api_key = 'YOUR API KEY'
api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}'
raw_df = requests.get(api_url).json()
df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float)
df = df[df.index >= start_date]
df.index = pd.to_datetime(df.index)
return df

aapl = get_historical_data('AAPL', '2010-01-01')
aapl.tail()

# WILLIAMS %R CALCULATION

def get_wr(high, low, close, lookback):
highh = high.rolling(lookback).max()
lowl = low.rolling(lookback).min()
wr = -100 * ((highh - close) / (highh - lowl))
return wr

aapl['wr_14'] = get_wr(aapl['high'], aapl['low'], aapl['close'], 14)
aapl.tail()

# WILLIAMS %R PLOT

plot_data = aapl[aapl.index >= '2020-01-01']

ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1)
ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1)
ax1.plot(plot_data['close'], linewidth = 2)
ax1.set_title('AAPL CLOSING PRICE')
ax2.plot(plot_data['wr_14'], color = 'orange', linewidth = 2)
ax2.axhline(-20, linewidth = 1.5, linestyle = '--', color = 'grey')
ax2.axhline(-80, linewidth = 1.5, linestyle = '--', color = 'grey')
ax2.set_title('AAPL WILLIAMS %R 14')
plt.show()

# MACD CALCULATION

def get_macd(price, slow, fast, smooth):
exp1 = price.ewm(span = fast, adjust = False).mean()
exp2 = price.ewm(span = slow, adjust = False).mean()
macd = pd.DataFrame(exp1 - exp2).rename(columns = {'close':'macd'})
signal = pd.DataFrame(macd.ewm(span = smooth, adjust = False).mean()).rename(columns = {'macd':'signal'})
hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'})
return macd, signal, hist

aapl['macd'] = get_macd(aapl['close'], 26, 12, 9)[0]
aapl['macd_signal'] = get_macd(aapl['close'], 26, 12, 9)[1]
aapl['macd_hist'] = get_macd(aapl['close'], 26, 12, 9)[2]
aapl = aapl.dropna()
aapl.tail()

# MACD PLOT

plot_data = aapl[aapl.index >= '2020-01-01']

def plot_macd(prices, macd, signal, hist):
ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1)
ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1)

ax1.plot(prices)
ax1.set_title('AAPL STOCK PRICES')
ax2.plot(macd, color = 'grey', linewidth = 1.5, label = 'MACD')
ax2.plot(signal, color = 'skyblue', linewidth = 1.5, label = 'SIGNAL')
ax2.set_title('AAPL MACD 26,12,9')

for i in range(len(prices)):
if str(hist[i])[0] == '-':
ax2.bar(prices.index[i], hist[i], color = '#ef5350')
else:
ax2.bar(prices.index[i], hist[i], color = '#26a69a')

plt.legend(loc = 'lower right')

plot_macd(plot_data['close'], plot_data['macd'], plot_data['macd_signal'], plot_data['macd_hist'])

# TRADING STRATEGY

def implement_wr_macd_strategy(prices, wr, macd, macd_signal):
buy_price = []
sell_price = []
wr_macd_signal = []
signal = 0

for i in range(len(wr)):
if wr[i-1] > -50 and wr[i] < -50 and macd[i] > macd_signal[i]:
if signal != 1:
buy_price.append(prices[i])
sell_price.append(np.nan)
signal = 1
wr_macd_signal.append(signal)
else:
buy_price.append(np.nan)
sell_price.append(np.nan)
wr_macd_signal.append(0)

elif wr[i-1] < -50 and wr[i] > -50 and macd[i] < macd_signal[i]:
if signal != -1:
buy_price.append(np.nan)
sell_price.append(prices[i])
signal = -1
wr_macd_signal.append(signal)
else:
buy_price.append(np.nan)
sell_price.append(np.nan)
wr_macd_signal.append(0)

else:
buy_price.append(np.nan)
sell_price.append(np.nan)
wr_macd_signal.append(0)

return buy_price, sell_price, wr_macd_signal

buy_price, sell_price, wr_macd_signal = implement_wr_macd_strategy(aapl['close'], aapl['wr_14'], aapl['macd'], aapl['macd_signal'])

# TRADING SIGNALS PLOT

plt.plot(aapl['close'])
plt.plot(aapl.index, buy_price, marker = '^', markersize = 10, color = 'green')
plt.plot(aapl.index, sell_price, marker = 'v', markersize = 10, color = 'r')

# POSITION

position = []
for i in range(len(wr_macd_signal)):
if wr_macd_signal[i] > 1:
position.append(0)
else:
position.append(1)

for i in range(len(aapl['close'])):
if wr_macd_signal[i] == 1:
position[i] = 1
elif wr_macd_signal[i] == -1:
position[i] = 0
else:
position[i] = position[i-1]

close_price = aapl['close']
wr = aapl['wr_14']
macd_line = aapl['macd']
signal_line = aapl['macd_signal']
wr_macd_signal = pd.DataFrame(wr_macd_signal).rename(columns = {0:'wr_macd_signal'}).set_index(aapl.index)
position = pd.DataFrame(position).rename(columns = {0:'wr_macd_position'}).set_index(aapl.index)

frames = [close_price, wr, macd_line, signal_line, wr_macd_signal, position]
strategy = pd.concat(frames, join = 'inner', axis = 1)

strategy.head()

# BACKTESTING

aapl_ret = pd.DataFrame(np.diff(aapl['close'])).rename(columns = {0:'returns'})
wr_macd_strategy_ret = []

for i in range(len(aapl_ret)):
try:
returns = aapl_ret['returns'][i] * strategy['wr_macd_position'][i]
wr_macd_strategy_ret.append(returns)
except:
pass

wr_macd_strategy_ret_df = pd.DataFrame(wr_macd_strategy_ret).rename(columns = {0:'wr_macd_returns'})

investment_value = 100000
number_of_stocks = floor(investment_value / aapl['close'][0])
wr_macd_investment_ret = []

for i in range(len(wr_macd_strategy_ret_df['wr_macd_returns'])):
returns = number_of_stocks * wr_macd_strategy_ret_df['wr_macd_returns'][i]
wr_macd_investment_ret.append(returns)

wr_macd_investment_ret_df = pd.DataFrame(wr_macd_investment_ret).rename(columns = {0:'investment_returns'})
total_investment_ret = round(sum(wr_macd_investment_ret_df['investment_returns']), 2)
profit_percentage = floor((total_investment_ret / investment_value) * 100)
print(cl('Profit gained from the W%R MACD strategy by investing $100k in AAPL : {}'.format(total_investment_ret), attrs = ['bold']))
print(cl('Profit percentage of the W%R MACD strategy : {}%'.format(profit_percentage), attrs = ['bold']))

# SPY ETF COMPARISON

def get_benchmark(start_date, investment_value):
spy = get_historical_data('SPY', start_date)['close']
benchmark = pd.DataFrame(np.diff(spy)).rename(columns = {0:'benchmark_returns'})

investment_value = investment_value
number_of_stocks = floor(investment_value/spy[0])
benchmark_investment_ret = []

for i in range(len(benchmark['benchmark_returns'])):
returns = number_of_stocks*benchmark['benchmark_returns'][i]
benchmark_investment_ret.append(returns)

benchmark_investment_ret_df = pd.DataFrame(benchmark_investment_ret).rename(columns = {0:'investment_returns'})
return benchmark_investment_ret_df

benchmark = get_benchmark('2010-01-01', 100000)

investment_value = 100000
total_benchmark_investment_ret = round(sum(benchmark['investment_returns']), 2)
benchmark_profit_percentage = floor((total_benchmark_investment_ret/investment_value)*100)
print(cl('Benchmark profit by investing $100k : {}'.format(total_benchmark_investment_ret), attrs = ['bold']))
print(cl('Benchmark Profit percentage : {}%'.format(benchmark_profit_percentage), attrs = ['bold']))
print(cl('W%R MACD Strategy profit is {}% higher than the Benchmark Profit'.format(profit_percentage - benchmark_profit_percentage), attrs = ['bold']))

 

Реализация MACD в Python

Схождение-расхождение скользящих средних (MACD) — это широко используемый индикатор в алгоритмической торговле и техническом анализе. Он состоит из трех основных компонентов:

  • Линия MACD — это разница между двумя экспоненциальными скользящими средними (EMA) цены ценной бумаги, обычно 12-дневной и 26-дневной EMA.
  • Сигнальная линия – это EMA линии MACD, обычно с периодом 9 дней.
  • Гистограмма представляет собой разницу между линией MACD и сигнальной линией.
МАКД. Источник

Распространенным торговым сигналом является пересечение линией MACD выше или ниже сигнальной линии. Пересечение выше сигнальной линии рассматривается как бычье, а пересечение ниже – как медвежье.

Когда линия Крузенштерна расходится с ценой финансового инструмента, это говорит о возможном развороте. Например, если цена устанавливает новые максимумы, а MACD нет, это может указывать на ослабление импульса.

Пересечение линии Крузенштерна выше или ниже нуля также является сигналом. Выше нуля в течение длительного периода времени говорит о восходящем тренде, в то время как ниже нуля указывает на нисходящий тренд.

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

Код на Python

Давайте проведем демонстрацию. Мы можем использовать библиотеку yfinance для сбора цен на акции TSLA. И мы можем использовать ta для вычисления MACD.

pip install yfinance, taimport yfinance as yf
import matplotlib.pyplot as plt
import ta

data = yf.download(‘TSLA’, start=’2020-01-01′, end=’2023-01-01′)
data.head()

Вычислим MACD:macd_object = ta.trend.MACD(data[‘Close’])
data[‘MACD’] = macd_object.macd()
data[‘MACD_Signal’] = macd_object.macd_signal()
data[‘MACD_Diff’] = macd_object.macd_diff()
data.tail()

class ta.trend.MACD(
close: pandas.core.series.Series,
window_slow: int = 26, window_fast: int = 12,
window_sign: int = 9, fillna: bool = False
)

  • Закрыть (Pandas. Series) — столбец «Закрыть» набора данных.
  • window_fast (int) — период n краткосрочный.
  • window_slow (int) — период n долгосрочный.
  • window_sign (int) — период n для сигнала.
  • fillna (bool) — если True, заполняет значения nan.

# Plotting
plt.figure(figsize=(14, 7))

# Plotting Close Price
plt.subplot(2, 1, 1)
plt.plot(data[‘Close’], label=’Close Price’)
plt.title(‘Tesla Stock Price and MACD’)
plt.legend()

# Plotting MACD
plt.subplot(2, 1, 2)
plt.plot(data[‘MACD’], label=’MACD Line’, color=’blue’)
plt.plot(data[‘MACD_Signal’], label=’Signal Line’, color=’red’)
plt.bar(data.index, data[‘MACD_Diff’], label=’Histogram’, color=’grey’, alpha=0.5)
plt.legend()

plt.show()

Участок. Изображение автора.

Источник

Источник

Источник

Источник

Источник