Блог им. uralpro

Получение real-time данных с Google Finance

AAPLpm1

Существует класс алгоритмов, основанных на корелляции цен активов на разных рынках. Для того, чтобы исследовать такие корелляции, например, между американским и российским рынком, необходимо иметь доступ к данным в реальном времени с западных бирж, поставку которых предлагают специальные провайдеры за довольно существенную плату.Однако, есть возможность использования вместо платного датафида парсинг данных 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
# 
# © 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 минут.

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

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

★18
15 комментариев
А гугл не забанит, если с него все время данные тянуть?
Тимофей Мартынов, нет, если периодичность запросов не будет слишком высока
avatar
uralpro, 'NASDAQ:AAPL', '543.55' что за цена такая?
avatar
maikl, так в статье у автора. На самом деле тикер AAPL перепутан с GOOG, а GOOG вообще неизвестно с чем. Остальные тикеры вроде верны. Это не ошибка программы, это какая-то путаница в тексте
avatar
uralpro, NASDAQ:GOOG' тоже самое… не понятно что с ценой.
avatar
Тимофей Мартынов, оттуда можно и MOEX красть для Smart-lab'a:) Другое дело, что в один не очень прекрасный день представитель биржи может задать вопрос, откуда же у Вас котировочки
avatar
Тимофей Мартынов, нет не забанит, проверено
а сколько стоит нормальный датафид?
avatar
Arsen G, если речь о MOEX, то где-то 20 тыс. в месяц через посредников для личного использования и 300 тыс. — при использовании на сайте
avatar
Том Сойер, 300 штук в месяц? :-О
Трейдер Квадратный, так точно. Биржа вместо популяризации через околорыночную тему (например, Smart-lab) избрала путь получения краткосрочной прибыли.
Что касается иностранных бирж, то тут легче — представители Nyse тут не тусуются
avatar
Том Сойер, т.е. если я держатель околорыночного сайта, то котировки онлайн, чтобы нарисовать графики, мне неоткуда получить? Жееесть. А Западные ресурсы, перепродающие потоки с фортс, мисекс и т.д. есть?
Трейдер Квадратный, здесь полный список авторизованных поставщиков котировок. MSN Финансы, например, берут у Morningstar, но на их сайте не нашёл стоимость предоставления такой услуги.

Да, Вам обязательно нужно покупать либо у биржи, либо у посредников. Если вздумаете брать котировки через свой торговый терминал и транслировать на сайт, то это нарушение договора с брокером: согласно нему, Вы не можете даже соседу сказать «сегодня утром Газпром был по 150 рублей»
avatar
Спереть можно? :)
avatar
Все же нужно иметь связку этих реал-тайм данных с историей, иначе толка от такого анализа будет мало. Ставить сервер нужно в любом случае.
avatar

теги блога uralpro

....все тэги



UPDONW
Новый дизайн