Избранное трейдера Sergey Pavlov
В этой статье я продолжаю делиться своим опытом по алгоритмической торговле моих роботов из TSLab на Американском фондовом рынке через брокера Interactive Brokers (IB). Спасибо всем, кто проявил интерес к моей первой статье, опубликованной в ноябре и за ваши комментарии. Это воодушевляет и вдохновляет к дальнейшей работе в этом направлении. Для тех, кто не успел ознакомиться с первой частью даю ссылочку внизу.
Для удобства весь материал был разбит на три части:
Часть 1- Особенности при подготовке к запуску TSLab на реал с IB– ноябрь 2017, ссылка https://smart-lab.ru/my/schardonnay/blog/all/
Часть 2 — Непосредственная работа терминалов TSLab и TWS
Часть 3- Часто встречающиеся проблемы
В данном выпуске идет рассмотрение второй части –как происходит работа TSLab и платформы брокера Trader Workstation (TWS) в течение основной рабочей сессии – с 9.30-16.00 ЕТ, порядок исполнения ордеров, проскальзывание и особенности комиссии. Все примеры сделок в этой статье реальные и приведены с моего торгового счета IB за последние два месяца торговли роботами.
IQFeed - это не самый дешёвый (но и не самый дорогой) провайдер исторических (и real-time) данных финансовых бирж и разнообразных trading venues. Со своими плюсами и минусами.
В этой короткой статье расскажу, как закачать исторические данные из IQFeed при минимальном знании языка Python.
Суть: Коллеги, предлагаю нативный совместный (shared) доступ (API) к провайдеру исторических биржевых данных IQFeed www.iqfeed.net за $20 в месяц.
Только исторические данные (тики бид-аск-трейд, минутки OHLCV и выше). Не real-time, не Level II.
Проект: некоммерческий, складчина. Технически уже всё работает.
Просьба: если тема Вам не интересна, но Вы знаете кому может быть полезна – дайте ему знать. Отдельное спасибо за ссылки-репосты.
История: Тики (bid-ask, миллисекунды, код сделки, extended hours) — до 180 дней, Минутки… Дневки, Недельки — с середины 2000х (минутки, как правило, с 2007го). Мировые фьючерсы (большинство). Опционы. Американские, Канадские, Лондонские акции (non-adjusted). Индексы… список столь длинный (сотни тысяч позиций), что проще проверить в режиме Free trial (см. в конце).
Форекса — нет (не подписаны, у Айкьюфида так себе данные по качеству).
Данные специально неотфильтрованы.
pw = pg.plot() timer = pg.QtCore.QTimer() def update(): pw.plot(x, y, clear=True) timer.timeout.connect(update) timer.start(100)
conda update conda
conda update anaconda— добавляем рисовалку
conda install pyqtgraph— делаем первый чарт
import pyqtgraph as pg from pyqtgraph.Qt import QtGui, QtCore # объявляем тип проги app = QtGui.QApplication([]) # объявляем базовое окно win = pg.GraphicsWindow() # ... и даем ему заголовок win.setWindowTitle('Мой Окно!') # открываем первую панель для рисования pane = win.addPlot() # от балды значения по 'x' и 'y' x = [1,2,3,4,5,6,7,8,9] y = [1,4,9,16,25,36,49,64,81] # нарисуем в панельке pane.plot(x,y,pen=('r'), symbol='o') # ...три...два...один...пуск .... п.ш..ш..ш :) app.exec_()
using System; using System.Net; using System.Text; namespace AuthMoexSmpl { class Program { static void Main(string[] args) { string authLink = "https://passport.moex.com/authenticate"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(authLink); request.ContentType = "text/plain; charset=utf-8"; request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes("login:password")); //свои данные request.PreAuthenticate = true; request.CookieContainer = new CookieContainer(); HttpWebResponse response = request.GetResponse() as HttpWebResponse; for(int i=0; i < response.Headers.Count; ++i) Console.WriteLine("\nHeader Name:{0}, Value :{1}",response.Headers.Keys[i],response.Headers[i]); } } }
D:\devel\net\AuthMoexSmpl>dotnet run Header Name:Cache-Control, Value :no-store, must-revalidate, no-cache, ma Header Name:Connection, Value :close Header Name:Date, Value :Fri, 10 Nov 2017 19:53:12 GMT Header Name:Pragma, Value :no-cache Header Name:ETag, Value :"xxxxxx" Header Name:Server, Value :nginx Header Name:Set-Cookie, Value :MicexPassportCert=xxxxxxx; domain=.moex.com; path=/, _passport_se m xxxxx; path=/; HttpOnly Header Name:Status, Value :200 OK Header Name:X-Runtime, Value :713 Header Name:X-Moex-Passport-Certificate, Value :xxxxxx Header Name:X-Powered-By, Value :Phusion Passenger 4.0.57 Header Name:Access-Control-Allow-Credentials, Value :true Header Name:Access-Control-Expose-Headers, Value :X-MicexPassport-Marker
using System; using System.Net; using System.Text; namespace AuthMoexSmpl { class Program { static void Main(string[] args) { string authLink = "https://passport.moex.com/authenticate"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(authLink); request.ContentType = "text/plain; charset=utf-8"; request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes("login:password")); // вносим свои данные request.PreAuthenticate = true; request.CookieContainer = new CookieContainer(); HttpWebResponse response = request.GetResponse() as HttpWebResponse; foreach (Cookie cook in response.Cookies) { Console.WriteLine("Cookie:"); Console.WriteLine("{0} = {1}", cook.Name, cook.Value); Console.WriteLine("Domain: {0}", cook.Domain); Console.WriteLine("Path: {0}", cook.Path); Console.WriteLine("Port: {0}", cook.Port); Console.WriteLine("Secure: {0}", cook.Secure); Console.WriteLine("When issued: {0}", cook.TimeStamp); Console.WriteLine("Expires: {0} (expired? {1})", cook.Expires, cook.Expired); Console.WriteLine("Don't save: {0}", cook.Discard); Console.WriteLine("Comment: {0}", cook.Comment); Console.WriteLine("Uri for comments: {0}", cook.CommentUri); Console.WriteLine("Version: RFC {0}" , cook.Version == 1 ? "2109" : "2965"); Console.WriteLine ("String: {0}", cook.ToString()); } } } }
D:\devel\net\AuthMoexSmpl>dotnet run Cookie: _passport_session = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx Domain: passport.moex.com Path: / Port: Secure: False When issued: 11.11.2017 01:55:42 Expires: 01.01.0001 00:00:00 (expired? False) Don't save: False Comment: Uri for comments: Version: RFC 2965 ...
reversed=1и оставить только строчку номер 15 в запросе
limit=1получим запрос вида
https://iss.moex.com/iss/engines/futures/markets/forts/securities/SiZ7/trades.json?reversed=1&limit=1Вариант автоматизации упрощенно:
using System; using System.Net; using System.IO; using System.Text; namespace GetLastPrice { class Program { static void Main(string[] args) { string newLine; string[] lastLine; string link = "https://iss.moex.com/iss/engines/futures/markets/forts/securities/SiZ7/trades.json?reversed=1&limit=1"; int count = 0; for (;;) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link); request.ContentType = "text/plain; charset=utf-8"; HttpWebResponse response = request.GetResponse() as HttpWebResponse; using (Stream responseStream = response.GetResponseStream()) { StreamReader sr = new StreamReader(responseStream, Encoding.UTF8); while ((newLine = sr.ReadLine()) != null) { if (count == 14) { if (newLine =="") break; else { lastLine = newLine.Split(","); Console.WriteLine("Volume is " + lastLine[6] +" at Price " + lastLine[5]); } } count++; } } count = 0; response.Close(); } } } }