Существует класс алгоритмов, основанных на корелляции цен активов на разных рынках. Для того, чтобы исследовать такие корелляции, например, между американским и российским рынком, необходимо иметь доступ к данным в реальном времени с западных бирж, поставку которых предлагают специальные провайдеры за довольно существенную плату.Однако, есть возможность использования вместо платного датафида парсинг данных real-time с сайта Google Finance. На таких данных высокочастотную стратегию, конечно, не построить, но для более медленных стратегий такой способ вполне подойдет. Впрочем, на высоких частотах сильной корелляции с американцами уже давно нет, и HFT алгоритмы с такой идеей не работают, а вот на длинных промежутках времени есть очень широкое поле для исследований. Как осуществить получение данных с Google Finance рассмотрено в блоге Pawel Lachowicz, перевод которой представлен ниже.
В этом посте мы рассмотрим, как получить данные реального времени, транслируемых на сайте Google Finance, для использования их в качестве исходных данных бэктеста или в реальном торговом приложении. Эти данные можно применять для внутридневных торговых систем. В заглавии поста показан пример отображения котировок Apple на Google Finance.
Ядро нашего кода, написанного на языке Python, представляет собой небольшую функцию, делающую основную работу.Для определенного тикера компании на сайте Google, она парсит данные непосредственно с сайта, получая последнюю текущую цену актива:
# Hacking Google Finance in Real-Time for Algorithmic Traders # # (c) 2014 QuantAtRisk.com, by Pawel Lachowicz import urllib, time, os, re, csv def fetchGF(googleticker): url="http://www.google.com/finance?&q=" txt=urllib.urlopen(url+googleticker).read() k=re.search('id="ref_(.*?)">(.*?)<',txt) if k: tmp=k.group(2) q=tmp.replace(',','') else: q="Nothing found for: "+googleticker return q
Для правильной работы программы нужно убедиться, что тикер написан верно (как будет показано ниже). Далее, отобразим на экране местное текущее время и затем заменим его на нью-йоркское (биржевое) время. Мы делаем это, так как будем получать цены акций, торгующихся на NYSE или NASDAQ. Если вы хотите получать значения английского индекса FTSE100, то нужно сменить время на универсальное (Лондон):
# отражаем местное время print(time.ctime()) print # устанавливаем время NYC os.environ['TZ']='America/New_York' time.tzset() t=time.localtime() # string print(time.ctime()) print
Сделав это, применим стороннюю функцию combine для помещения всех считанных данных в переменную-список языка Python:
def combine(ticker): quote=fetchGF(ticker) # используем функцию ядра t=time.localtime() # фиксируем момент времени output=[t.tm_year,t.tm_mon,t.tm_mday,t.tm_hour, # строим список t.tm_min,t.tm_sec,ticker,quote] return output
На вход мы подаем тикер интересующей нас компании с сайта Google:
ticker="NASDAQ:AAPL"
для которого открываем новый текстовый файл, где будем сохранять все запросы в реальном времени:
# задаем имя файла для записи fname="aapl.dat" # удаляем файл, если он уже существует os.path.exists(fname) and os.remove(fname)
Далее создаем окончательный цикл по всему торговому дню. В нашем примере мы получаем последние данные в 16:00:59 по нью-йоркскому времени. Ключевой параметр программы - переменная freq, где мы задаем частоту внутридневной нарезки данных (в секундах). Автор определил, что оптимальным значением будет 600 сек (10 мин), так как при более частых запросах Google Finance может зафиксировать высокую активность с вашего IP и посчитать это флудом. Впрочем, вы можете найти наименьшее значение для вашего IP.
freq=600 # запрашиваем данные каждые 600 sec (10 min) with open(fname,'a') as f: writer=csv.writer(f,dialect="excel") #,delimiter=" ") while(t.tm_hour<=16): if(t.tm_hour==16): while(t.tm_min<01): data=combine(ticker) print(data) writer.writerow(data) # записываем данные в файл time.sleep(freq) else: break else: for ticker in tickers: data=combine(ticker) print(data) writer.writerow(data) # записываем данные в файл time.sleep(freq) f.close()
Чтобы проверить, как программа работает на практике, автор запустил ее 9 января 2014 года по времени Нью-Йорка 03:31:19. Полученные данные записались в файл в следующем виде:
Thu Jan 9 03:31:19 2014 [2014, 1, 8, 11, 31, 19, '543.71'] [2014, 1, 8, 11, 41, 22, '543.66'] [2014, 1, 8, 11, 51, 22, '544.22'] [2014, 1, 8, 12, 1, 23, '544.80'] [2014, 1, 8, 12, 11, 24, '544.32'] [2014, 1, 8, 12, 21, 25, '544.86'] [2014, 1, 8, 12, 31, 27, '544.47'] [2014, 1, 8, 12, 41, 28, '543.76'] [2014, 1, 8, 12, 51, 29, '543.86'] [2014, 1, 8, 13, 1, 30, '544.00'] [2014, 1, 8, 13, 11, 31, 'Nothing found for: NASDAQ:AAPL'] [2014, 1, 8, 13, 21, 33, '543.32'] [2014, 1, 8, 13, 31, 34, '543.84'] [2014, 1, 8, 13, 41, 36, '544.26'] [2014, 1, 8, 13, 51, 37, '544.10'] [2014, 1, 8, 14, 1, 39, '544.30'] [2014, 1, 8, 14, 11, 40, '543.88'] [2014, 1, 8, 14, 21, 42, '544.29'] [2014, 1, 8, 14, 31, 45, '544.15'] ...
Важно отметить, что время, которое мы записываем и пытаемся ассоциировать со временем полученной котировки, является локальным временем компьютера, поэтому не ожидайте равных временных интервалов между значениями и большой точности фиксации. Однако в нашем случае, когда мы хотим оценить корелляцию на довольно длительных промежутках, точность определения времени не имеет столь важного значения, как это бывает в случае высокочастотных стратегий. Обратим внимание , что если интернет соединение неустойчиво, то могут появляться пропуски в данных, как это видно на приведенном выше примере.
Представленный код может быть легко модифицирован, если вы хотите получать данные сразу по нескольким активам. Просто замените часть кода приведенной выше программы, начиная с определения переменной ticker, нижеследующим кодом:
tickers=["NASDAQ:AAPL","NASDAQ:GOOG","NASDAQ:BIDU","NYSE:IBM", \ "NASDAQ:INTC","NASDAQ:MSFT","NYSEARCA:SPY"] # определяем имя выходного файла fname="portfolio.dat" # удаляем файл, если он уже существует os.path.exists(fname) and os.remove(fname) freq=600 # запрашиваем данные каждые 600 sec (10 min) with open(fname,'a') as f: writer=csv.writer(f,dialect="excel") #,delimiter=" ") while(t.tm_hour<=16): if(t.tm_hour==16): while(t.tm_min<01): #for ticker in tickers: data=combine(ticker) print(data) writer.writerow(data) time.sleep(freq) else: break else: for ticker in tickers: data=combine(ticker) print(data) writer.writerow(data) time.sleep(freq) f.close()
Запись котировок в реальном времени получилась такой:
Thu Jan 9 07:01:43 2014 [2014, 1, 8, 15, 1, 44, 'NASDAQ:AAPL', '543.55'] [2014, 1, 8, 15, 1, 44, 'NASDAQ:GOOG', '1140.30'] [2014, 1, 8, 15, 1, 45, 'NASDAQ:BIDU', '182.65'] [2014, 1, 8, 15, 1, 45, 'NYSE:IBM', '187.97'] [2014, 1, 8, 15, 1, 46, 'NASDAQ:INTC', '25.40'] [2014, 1, 8, 15, 1, 47, 'NASDAQ:MSFT', '35.67'] [2014, 1, 8, 15, 1, 47, 'NYSEARCA:SPY', '183.43'] [2014, 1, 8, 15, 11, 48, 'NASDAQ:AAPL', '543.76'] [2014, 1, 8, 15, 11, 49, 'NASDAQ:GOOG', '1140.06'] [2014, 1, 8, 15, 11, 49, 'NASDAQ:BIDU', '182.63'] [2014, 1, 8, 15, 11, 50, 'NYSE:IBM', '187.95'] [2014, 1, 8, 15, 11, 51, 'NASDAQ:INTC', '25.34'] [2014, 1, 8, 15, 11, 52, 'NASDAQ:MSFT', '35.67'] [2014, 1, 8, 15, 11, 53, 'NYSEARCA:SPY', '183.34'] ...
где мы можем увидеть значения текущих цен для 6 акций и одного биржевого фонда ETF через каждые 10 минут.
В заключении, от себя добавлю, что было бы интересно исследовать корелляцию между американскими и российскими сырьевыми компаниями, там может присутсвовать хороший временной гэп.
Для получения realtime и history данных я использую iqFeed, несмотря на то что он платный, цена приемлима, всего около 70$ в месяц.
Нужно отметить, что цена iqFeed зависит от того на какое кол-во инструментов и площадок подписаны. $70 это минимум. Плюс нужно добавить около $300 за доступ к их документации по API.