В этой статье мы мельком коснемся индикаторов, и, на примере биржи Полоникс, построим такие же, используя язык программирования Python и библиотеку TA-Lib.
Эти знания пригодятся, когда вы захотите использовать расчетные данные в своем торговом боте, либо построить нужный вам набор индикаторов и использовать как вспомогательный инструмент для торговли.
Торговля была бы намного проще и приятнее, если бы вы знали будущее. Вы бы закупались в нужный момент, и продавали на самом пике.. Знакомая мысль?
Тысячи людей пытались найти закономерности рынка, выстроить математические модели для расчета падения и роста курса, кое-кто потратил на это почти всю жизнь, и многие более-менее приблизились к решению. Более-менее - это значит что они теперь знают о бирже немного больше других. Но, когда вопрос касается денег, даже 0.5% знания могут принести серьезные дивиденды... Если эти знания истинны, конечно.
Существуют такие вещи, как индикаторы. Если говорить упрощенно, то индикатор - это математическая функция, которая принимает на вход историю торгов за определенный период, и возвращает некоторый прогноз. Некоторые индикаторы оценивают объемы торгов, некоторые - цены сделок, в любом случае за каждым проверенным индикатором стоит выверенная математическая модель. А так же для каждого индикатора есть определенные инструкции по трактованию результатов.
Довольно воды - давайте рассмотрим на простых примерах, и подумаем, как мы можем это использовать в автоматизированной торговле.
Вот перед нами окно Полоникса – сейчас выбрана пара BTC-ETH, период 24 часа, свечи по 5 минут. Мы видим соответственно сами свечи (как они строятся, мы уже разбирали), за ними затененные столбики то ли серого, то ли светло-зеленого цвета – объемы торгов по паре (сколько было вбухано денег при том курсе), и кучу разноцветных полос тут и там. Так вот эти полосы как раз отображают посчитанные данные некоторых индикаторов, которые можно использовать при торговле.
EMA, SMA и прочие MA – это скользящие средние (упрощение графика). На любом трейдерском сайте вы найдете тысячу и один способ по их использованию, я процитирую пример из википедии:
MACD тоже неплохо разобран везде – и на вики, и на нашем сайте есть видео, тоже немного процитирую:
Я не буду сейчас заострять внимание на каждом индикаторе – это тема для отдельных будущих статей, но покажу, как их получать, строить и использовать для своих целей.
Так же маленький хинт – на графике полоникса сверху слева есть шестеренка – вы можете нажать её и поиграться с настройкой индикаторов.
Для работы нам потребуется библиотека для научных расчетов numpy, библиотека TA-Lib и модуль requests. Так же понадобится пакет matplotlib, с его помощью мы будем рисовать графики. Ну и установленный Python, конечно. У меня установлен Python 3.5.2 разрядность 32.
pip install numpy pip install requests pip install matplotlib
Подготовка окончена.
Полоникс предоставляет публичный API-метод для построения графика – дает цены открытия, закрытия, минимальной и максимальной цены за период, сгруппированный по указанным периодам. Метод returnChartData, пример можно посмотреть по ссылке. Мы будем использовать эти данные, что бы
График будем строить по паре BTC-ETH, за прошедшие 24 часа с группировкой по 5 минут. Для этого напишем небольшой скрипт. Если нужны данные по другим парам, меняйте в коде BTC_ETH на что вам угодно.
import numpy import talib import requests import json import time from matplotlib.finance import candlestick2_ohlc import matplotlib.pyplot as plt import matplotlib.ticker as ticker import datetime as datetime start_time = time.time() - 24*60*60 resource = requests.get("https://poloniex.com/public?command=returnChartData¤cyPair=BTC_ETH&start=%s&end=9999999999&period=300" % start_time) data = json.loads(resource.text) quotes = {} quotes['open']=numpy.asarray([item['open'] for item in data]) quotes['close']=numpy.asarray([item['close'] for item in data]) quotes['high']=numpy.asarray([item['high'] for item in data]) quotes['low']=numpy.asarray([item['low'] for item in data]) xdate=[datetime.datetime.fromtimestamp(item['date']) for item in data] fig, ax = plt.subplots() candlestick2_ohlc(ax,quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6) ax.xaxis.set_major_locator(ticker.MaxNLocator(6)) def chart_date(x,pos): try: return xdate[int(x)] except IndexError: return '' ax.xaxis.set_major_formatter(ticker.FuncFormatter(chart_date)) fig.autofmt_xdate() fig.tight_layout() plt.show()
При запуске он будет выдавать предупреждение MatplotlibDeprecationWarning: The finance module has been deprecated in mpl 2.0 and will be removed in mpl 2.2. Please use the module mpl_finance instead., но не обращайте на него внимание, он просто предупреждает, что в будущем код надо писать по другому. Но что бы писать прямо сейчас такой код, как он хочет, надо скачивать отдельные библиотеки, подключать их.. В общем, не берите в голову.
Итак, мы запустили код, и что мы видим? Хм, график! Совпадают данные с полониксом? Ага)
Но в самом графике смысла нет – его можно и так смотреть на полониксе. Давайте попробуем построить данные для индикатора?
На Полониксе в верхней части используются SMA и EMA – давайте начнем с чего-то одного. Значит так, SMA строится с интервалом в 50 минут? Оок. Немного меняем скрипт:
import numpy import talib import requests import json import time from matplotlib.finance import candlestick2_ohlc import matplotlib.pyplot as plt import matplotlib.ticker as ticker import datetime as datetime start_time = time.time() - 24*60*60 resource = requests.get("https://poloniex.com/public?command=returnChartData¤cyPair=BTC_ETH&start=%s&end=9999999999&period=300" % start_time) data = json.loads(resource.text) quotes = {} quotes['open']=numpy.asarray([item['open'] for item in data]) quotes['close']=numpy.asarray([item['close'] for item in data]) quotes['high']=numpy.asarray([item['high'] for item in data]) quotes['low']=numpy.asarray([item['low'] for item in data]) xdate=[datetime.datetime.fromtimestamp(item['date']) for item in data] fig, ax = plt.subplots() candlestick2_ohlc(ax,quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6) ax.xaxis.set_major_locator(ticker.MaxNLocator(6)) def chart_date(x,pos): try: return xdate[int(x)] except IndexError: return '' ax.xaxis.set_major_formatter(ticker.FuncFormatter(chart_date)) fig.autofmt_xdate() fig.tight_layout() sma = talib.SMA(quotes['close'], timeperiod=50) print(sma) ax.plot(sma) plt.show()
Работает… Так же обратили внимание, что в коде есть строка print(sma)? Я специально в отладочную консоль вывел посчитанные данные:
В «нормальной» жизни вам (наверное) не нужны графики – вам нужны именно эти цифры. Т.е. ваш бот может получать такой массив данных, и понимать – тренд растет, либо тренд падает, цена биржи пересекает тренд снизу вверх или сверху вниз и т.п… Но в этой статье мы рисуем графики для визуализации принципа, поэтому пока-что мы их анализировать не будем.. И print() писать тоже)
Так же график начинается не с начала, а с некоторым интервалом – но тут все просто. Мы берем данные за 24 часа, поэтому в начале работы скрипту нечего считать – мы же ведь за 50 минут строим? Это легко поправить, но я не хочу усложнять код и объяснять, почему и как усложнил, сути это не поменяет.
Теперь надо добавить EMA с периодом в 30 минут. Дополняем код:
import numpy import talib import requests import json import time from matplotlib.finance import candlestick2_ohlc import matplotlib.pyplot as plt import matplotlib.ticker as ticker import datetime as datetime start_time = time.time() - 24*60*60 resource = requests.get("https://poloniex.com/public?command=returnChartData¤cyPair=BTC_ETH&start=%s&end=9999999999&period=300" % start_time) data = json.loads(resource.text) quotes = {} quotes['open']=numpy.asarray([item['open'] for item in data]) quotes['close']=numpy.asarray([item['close'] for item in data]) quotes['high']=numpy.asarray([item['high'] for item in data]) quotes['low']=numpy.asarray([item['low'] for item in data]) xdate=[datetime.datetime.fromtimestamp(item['date']) for item in data] fig, ax = plt.subplots() candlestick2_ohlc(ax,quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6) ax.xaxis.set_major_locator(ticker.MaxNLocator(6)) def chart_date(x,pos): try: return xdate[int(x)] except IndexError: return '' ax.xaxis.set_major_formatter(ticker.FuncFormatter(chart_date)) fig.autofmt_xdate() fig.tight_layout() sma = talib.SMA(quotes['close'], timeperiod=50) ax.plot(sma) ema = talib.EMA(quotes['close'], timeperiod=20) ax.plot(ema) plt.show()
Мне, в целом, нравится. Но надо больше графиков!
Теперь я хочу добавить MACD, но он на этот график не ложится – там совсем другие значения, слишком маленькие. Все просто, сейчас мы будем рисовать сразу ТРИ графика с одной и той-же осью X. На первом графике мы оставим всё как есть, на второй вынесем линию MACD и сигнальную, а на третью – гистограмму MACD. Конечно, можно уместить все в двух графиках, как на Полониксе, но так просто нагляднее.
Меняем код:
import numpy import talib import requests import json import time from matplotlib.finance import candlestick2_ohlc import matplotlib.pyplot as plt import matplotlib.ticker as ticker import datetime as datetime start_time = time.time() - 24*60*60 resource = requests.get("https://poloniex.com/public?command=returnChartData¤cyPair=BTC_ETH&start=%s&end=9999999999&period=300" % start_time) data = json.loads(resource.text) quotes = {} quotes['open']=numpy.asarray([item['open'] for item in data]) quotes['close']=numpy.asarray([item['close'] for item in data]) quotes['high']=numpy.asarray([item['high'] for item in data]) quotes['low']=numpy.asarray([item['low'] for item in data]) xdate=[datetime.datetime.fromtimestamp(item['date']) for item in data] fig, ax = plt.subplots(3, sharex=True) candlestick2_ohlc(ax[0], quotes['open'],quotes['high'],quotes['low'],quotes['close'],width=0.6) ax[0].xaxis.set_major_locator(ticker.MaxNLocator(6)) def chart_date(x,pos): try: return xdate[int(x)] except IndexError: return '' ax[0].xaxis.set_major_formatter(ticker.FuncFormatter(chart_date)) fig.autofmt_xdate() fig.tight_layout() sma = talib.SMA(quotes['close'], timeperiod=50) ax[0].plot(sma) ema = talib.EMA(quotes['close'], timeperiod=20) ax[0].plot(ema) macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=12, slowperiod=26, signalperiod=9) ax[1].plot(macd, color="y") ax[1].plot(macdsignal) hist_data = [] for elem in macdhist: if not numpy.isnan(elem): v = 0 if numpy.isnan(elem) else elem hist_data.append(v*100) ax[2].fill_between([x for x in range(len(macdhist))], 0,macdhist) plt.show()
Ну что ж, теперь на втором графике рисуются линии MACD, на третьем – гистограмма.. Если хотите гистограмму отправить на второй график, поменяйте ax[2].fill_between на ax[1] .fill_between и т.п.
Общий принцип просто – вы получаете данные с биржи, вызываете функцию с нужным индикатором, передаете ей данные, и результат работы рисуете на графике или используете в иных целях.
Если разберетесь с этим, сможете строить и комбинировать свои индикаторы в тех комбинациях, в которых сочтете нужными. Полный список индикаторов, поддерживаемых библиотекой, вы можете найти тут. Обратите внимание, что в разные функции нужно передавать разные параметры, а так же некоторые возвращают один набор данных (EMA, например), а некоторые - несколько (MACD, например, возвращает сразу три)
А я желаю вам удачи и процветания, и не стесняйтесь задавать вопросы в комментариях ;)