Блог им. TaurusGOLD

📋 Создание Excel файла для торговли на ММВБ через QUIK

🚀 Шаг 1: Создаем новый Excel файл

1.1. Структура листов:

  • 📊 Котировки - текущие цены инструментов

  • 🎯 Торговля - ручная отправка заявок

  • 🤖 Автоторговля - автоматические стратегии

  • 💼 Портфель - текущие позиции

  • ⚙ Настройки - параметры подключения

  • 📈 Графики - визуализация данных



🎨 Шаг 2: Настраиваем листы

Лист «Настройки» (Settings)

A1: "НАСТРОЙКИ ПОДКЛЮЧЕНИЯ К QUIK"
A3: "DDE Service:"      B3: "QLUA"
A4: "DDE Topic:"        B4: "QuikTrans2"
A5: "Торговый счет:"    B5: "L01-00000F00"
A6: "Клиентский код:"   B6: ""

A8: "СПИСОК ИНСТРУМЕНТОВ"
A9: "Тикер"   B9: "Название"        C9: "Класс"   D9: "Лот"
A10: "GAZP"   B10: "Газпром"        C10: "TQBR"   D10: "10"
A11: "SBER"   B11: "Сбербанк"       C11: "TQBR"   D11: "10"
A12: "LKOH"   B12: "Лукойл"         C12: "TQBR"   D12: "1"
A13: "GMKN"   B13: "Норникель"      C13: "TQBR"   D13: "1"

 

Лист «Котировки» (Quotes)

A1: "ТЕКУЩИЕ КОТИРОВКИ"
A2: "Тикер"   B2: "Послед."   C2: "Бид"   D2: "Оффер"   E2: "Объем"   F2: "Время"   G2: "Изменение %"

Лист «Торговля» (Trading)

A1: "РУЧНАЯ ТОРГОВЛЯ"
A2: "Тикер"   B2: "Операция"   C2: "Кол-во лотов"   D2: "Цена"   E2: "Статус"   F2: "ID заявки"   G2: "Действие"

 

💻 Шаг 3: Добавляем VBA код

3.1. Откройте редактор VBA (ALT + F11)
3.2. Добавьте новый модуль и вставьте код:

vba
' Модуль для торговли через QUIK DDE
Option Explicit

' Константы подключения
Private Const QUIK_DDE_SERVICE As String = "QLUA"
Private Const QUIK_DDE_TOPIC As String = "QuikTrans2"
Private Const TRANS2_TABLE As String = "TRANS2"

' Глобальные переменные
Private ddeChannel As Long
Private isConnected As Boolean

' ==================== ОСНОВНЫЕ ФУНКЦИИ ====================

' Инициализация подключения к QUIK
Public Sub InitializeQUIKConnection()
    On Error GoTo ErrorHandler
    
    ' Завершаем предыдущее подключение
    If ddeChannel > 0 Then
        DDETerminate ddeChannel
    End If
    
    ' Инициируем DDE канал
    ddeChannel = DDEInitiate(QUIK_DDE_SERVICE, QUIK_DDE_TOPIC)
    
    If ddeChannel > 0 Then
        isConnected = True
        UpdateStatus "✅ Подключено к QUIK"
        ThisWorkbook.Sheets("Настройки").Range("B1").Value = "ПОДКЛЮЧЕНО"
    Else
        isConnected = False
        UpdateStatus "❌ Ошибка подключения к QUIK"
        ThisWorkbook.Sheets("Настройки").Range("B1").Value = "ОШИБКА"
    End If
    
    Exit Sub
ErrorHandler:
    UpdateStatus "Ошибка инициализации: " & Err.Description
End Sub

' Отправка лимитной заявки
Public Sub SendLimitOrder()
    On Error GoTo ErrorHandler
    
    If Not isConnected Then
        InitializeQUIKConnection
        If Not isConnected Then Exit Sub
    End If
    
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Торговля")
    
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    Dim i As Long
    For i = 3 To lastRow ' Начинаем с строки 3 (после заголовков)
        
        ' Проверяем кнопку отправки
        If ws.Cells(i, "G").Value = "ОТПРАВИТЬ" Then
            
            Dim ticker As String, operation As String
            Dim quantity As Long, price As Double
            Dim classCode As String, account As String
            
            ' Получаем данные из строки
            ticker = Trim(ws.Cells(i, "A").Value)
            operation = UCase(Trim(ws.Cells(i, "B").Value))
            quantity = ws.Cells(i, "C").Value
            price = ws.Cells(i, "D").Value
            
            ' Получаем дополнительные параметры из настроек
            classCode = GetClassCode(ticker)
            account = GetSetting("Торговый счет")
            
            If ticker = "" Or quantity <= 0 Or price <= 0 Then
                ws.Cells(i, "E").Value = "ОШИБКА: Неверные данные"
                ws.Cells(i, "G").Value = "ПОВТОРИТЬ"
                GoTo NextRow
            End If
            
            ' Отправляем транзакцию
            Dim transId As String
            transId = SendTransaction(ticker, classCode, operation, quantity, price, account)
            
            If transId <> "" Then
                ws.Cells(i, "E").Value = "ОТПРАВЛЕНО"
                ws.Cells(i, "F").Value = transId
                ws.Cells(i, "G").Value = "✅ ОТПРАВЛЕНО"
                UpdateStatus "Заявка отправлена: " & ticker & " " & operation & " " & quantity & " @ " & price
            Else
                ws.Cells(i, "E").Value = "ОШИБКА ОТПРАВКИ"
                ws.Cells(i, "G").Value = "ПОВТОРИТЬ"
            End If
        End If
        
NextRow:
    Next i
    
    Exit Sub
ErrorHandler:
    UpdateStatus "Ошибка отправки заявки: " & Err.Description
End Sub

' Функция отправки транзакции в QUIK
Private Function SendTransaction(ticker As String, classCode As String, _
                                operation As String, quantity As Long, _
                                price As Double, account As String) As String
    
    If ddeChannel <= 0 Then
        SendTransaction = ""
        Exit Function
    End If
    
    ' Генерируем уникальный ID транзакции
    Dim transId As String
    transId = "XL" & Format(Now, "yymmddhhnnss")
    
    ' Формируем строку транзакции для таблицы TRANS2
    Dim transData As String
    transData = "CLASSCODE=" & classCode & ";" & _
                "SECCODE=" & ticker & ";" & _
                "ACTION=NEW_ORDER;" & _
                "ACCOUNT=" & account & ";" & _
                "OPERATION=" & operation & ";" & _
                "PRICE=" & Format(price, "0.00") & ";" & _
                "QUANTITY=" & quantity & ";" & _
                "TYPE=L;" & _
                "TRANS_ID=" & transId & ";" & _
                "BROKERREF=EXCEL_TRADE"
    
    ' Отправляем через DDE
    DDEPoke ddeChannel, TRANS2_TABLE, transData
    
    SendTransaction = transId
End Function

' ==================== ПОЛУЧЕНИЕ ДАННЫХ ИЗ QUIK ====================

' Обновление котировок
Public Sub UpdateQuotes()
    On Error GoTo ErrorHandler
    
    If Not isConnected Then Exit Sub
    
    Dim wsSettings As Worksheet, wsQuotes As Worksheet
    Set wsSettings = ThisWorkbook.Sheets("Настройки")
    Set wsQuotes = ThisWorkbook.Sheets("Котировки")
    
    ' Очищаем старые данные (кроме заголовков)
    If wsQuotes.Cells(2, 1).Value <> "" Then
        wsQuotes.Range("A3:G100").ClearContents
    End If
    
    Dim i As Long, rowCount As Long
    rowCount = 0
    
    ' Проходим по списку инструментов из настроек
    Dim lastRow As Long
    lastRow = wsSettings.Cells(wsSettings.Rows.Count, "A").End(xlUp).Row
    
    For i = 10 To lastRow ' Начинаем с строки 10 где список инструментов
        Dim ticker As String
        ticker = Trim(wsSettings.Cells(i, "A").Value)
        
        If ticker = "" Then Exit For
        
        ' Получаем данные по инструменту
        Dim lastPrice As String, bidPrice As String, askPrice As String
        Dim volume As String, timeStamp As String
        
        lastPrice = GetDDEValue(ticker, "LAST")
        bidPrice = GetDDEValue(ticker, "BID")
        askPrice = GetDDEValue(ticker, "OFFER")
        volume = GetDDEValue(ticker, "VOLUME")
        timeStamp = Format(Now, "hh:nn:ss")
        
        ' Записываем в таблицу котировок
        rowCount = rowCount + 1
        wsQuotes.Cells(2 + rowCount, 1).Value = ticker
        wsQuotes.Cells(2 + rowCount, 2).Value = lastPrice
        wsQuotes.Cells(2 + rowCount, 3).Value = bidPrice
        wsQuotes.Cells(2 + rowCount, 4).Value = askPrice
        wsQuotes.Cells(2 + rowCount, 5).Value = volume
        wsQuotes.Cells(2 + rowCount, 6).Value = timeStamp
        
        ' Расчет изменения цены
        If IsNumeric(lastPrice) Then
            If rowCount > 1 Then
                Dim prevPrice As Double
                On Error Resume Next
                prevPrice = wsQuotes.Cells(1 + rowCount, 2).Value
                If prevPrice > 0 Then
                    Dim changePct As Double
                    changePct = (lastPrice - prevPrice) / prevPrice * 100
                    wsQuotes.Cells(2 + rowCount, 7).Value = changePct
                    ' Раскрашиваем ячейку
                    If changePct > 0 Then
                        wsQuotes.Cells(2 + rowCount, 7).Interior.Color = RGB(200, 255, 200)
                    ElseIf changePct < 0 Then
                        wsQuotes.Cells(2 + rowCount, 7).Interior.Color = RGB(255, 200, 200)
                    End If
                End If
            End If
        End If
    Next i
    
    UpdateStatus "Котировки обновлены: " & rowCount & " инструментов"
    
    Exit Sub
ErrorHandler:
    UpdateStatus "Ошибка обновления котировок: " & Err.Description
End Sub

' Получение значения через DDE
Private Function GetDDEValue(ticker As String, param As String) As String
    On Error Resume Next
    
    Dim value As String
    value = DDERequest(ddeChannel, ticker & "|" & param)
    
    If Err.Number <> 0 Then
        GetDDEValue = "N/A"
    Else
        GetDDEValue = value
    End If
End Function

' ==================== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ====================

' Получение класса инструмента
Private Function GetClassCode(ticker As String) As String
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Настройки")
    
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    Dim i As Long
    For i = 10 To lastRow
        If Trim(ws.Cells(i, "A").Value) = ticker Then
            GetClassCode = ws.Cells(i, "C").Value
            Exit Function
        End If
    Next i
    
    GetClassCode = "TQBR" ' По умолчанию для акций
End Function

' Получение настройки
Private Function GetSetting(settingName As String) As String
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Настройки")
    
    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
    Dim i As Long
    For i = 3 To lastRow
        If ws.Cells(i, "A").Value = settingName Then
            GetSetting = ws.Cells(i, "B").Value
            Exit Function
        End If
    Next i
    
    GetSetting = ""
End Function

' Обновление статуса
Private Sub UpdateStatus(message As String)
    ThisWorkbook.Sheets("Торговля").Range("H1").Value = message
    Debug.Print Format(Now, "hh:nn:ss") & " - " & message
End Sub

' ==================== АВТОМАТИЗАЦИЯ ====================

' Запуск автоматического обновления
Public Sub StartAutoUpdate()
    UpdateStatus "Запуск автоматического обновления..."
    
    ' Обновляем котировки сразу
    UpdateQuotes
    
    ' Запускаем периодическое обновление (каждые 10 секунд)
    Application.OnTime Now + TimeValue("00:00:10"), "ScheduledUpdate"
End Sub

' Плановое обновление
Public Sub ScheduledUpdate()
    On Error GoTo ErrorHandler
    
    If ThisWorkbook.Sheets("Настройки").Range("B2").Value = "ДА" Then
        UpdateQuotes
        UpdatePortfolio
    End If
    
    ' Планируем следующее обновление
    Application.OnTime Now + TimeValue("00:00:10"), "ScheduledUpdate"
    
    Exit Sub
ErrorHandler:
    UpdateStatus "Ошибка планового обновления: " & Err.Description
    Application.OnTime Now + TimeValue("00:00:30"), "ScheduledUpdate"
End Sub

' Остановка автоматического обновления
Public Sub StopAutoUpdate()
    On Error Resume Next
    Application.OnTime EarliestTime:=Now + TimeValue("00:00:01"), _
                      Procedure:="ScheduledUpdate", Schedule:=False
    UpdateStatus "Автообновление остановлено"
End Sub

' Обновление портфеля
Public Sub UpdatePortfolio()
    ' Здесь можно добавить логику обновления позиций
    ' через DDE запросы к таблицам QUIK (depo_limits, money_limits)
End Sub

' ==================== ОБРАБОТЧИКИ СОБЫТИЙ ====================

' Автозапуск при открытии файла
Private Sub Workbook_Open()
    UpdateStatus "Файл открыт. Для подключения к QUIK нажмите 'Подключиться'"
    
    ' Инициализируем интерфейс
    InitializeInterface
End Sub

' Инициализация интерфейса
Private Sub InitializeInterface()
    ' Добавляем кнопки на лист торговли
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Торговля")
    
    ' Создаем заголовки если их нет
    If ws.Range("A1").Value = "" Then
        ws.Range("A1:G1").Value = Array("Тикер", "Операция", "Кол-во лотов", "Цена", "Статус", "ID заявки", "Действие")
    End If
    
    UpdateStatus "Готов к работе"
End Sub

🎯 Шаг 4: Добавляем кнопки управления

4.1. На листе «Торговля» создаем кнопки:

vba
' В редакторе VBA добавьте этот код в модуль листа "Торговля"

' Кнопка "Подключиться к QUIK"
Private Sub btnConnect_Click()
    InitializeQUIKConnection
End Sub

' Кнопка "Обновить котировки"  
Private Sub btnUpdateQuotes_Click()
    UpdateQuotes
End Sub

' Кнопка "Отправить заявки"
Private Sub btnSendOrders_Click()
    SendLimitOrder
End Sub

' Кнопка "Автообновление ВКЛ"
Private Sub btnAutoOn_Click()
    ThisWorkbook.Sheets("Настройки").Range("B2").Value = "ДА"
    StartAutoUpdate
End Sub

' Кнопка "Автообновление ВЫКЛ"
Private Sub btnAutoOff_Click()
    ThisWorkbook.Sheets("Настройки").Range("B2").Value = "НЕТ" 
    StopAutoUpdate
End Sub

📋 Шаг 5: Инструкция по использованию

5.1. Первый запуск:

  1. Откройте QUIK и подключитесь к брокеру

  2. Откройте Excel файл

  3. Нажмите «Подключиться к QUIK»

  4. Проверьте статус подключения

5.2. Ручная торговля:

  1. На листе «Торговля» введите:

    • Тикер (GAZP, SBER и т.д.)

    • Операция (BUY/SELL)

    • Кол-во лотов

    • Цену

  2. Нажмите «ОТПРАВИТЬ» в столбце G

  3. Следите за статусом в столбце E

5.3. Автоматическое обновление:

  • Включите автообновление для получения котировок каждые 10 секунд

🔧 Шаг 6: Настройка безопасности Excel

  1. Файл → Параметры → Центр управления безопасностью

  2. Параметры макросов → Включить все макросы

  3. Надежные издатели → Доверять доступ к объектной модели VBA

💾 Шаг 7: Сохранение файла

Сохраните как «Торговля ММВБ.xlsm» (с поддержкой макросов)

 🚀 Тестируйте на демо-счете перед реальной торговлей.

 






Данная публикация является личным мнением автора. Мнение владельца сайта может не совпадать с мнением автора.
  • обсудить на форуме:
  • QUIK
587 | ★4
3 комментария
а зачем?)
avatar
Йонатан Берсон, 
avatar

Читайте на SMART-LAB:
Фото
Календарь первички ВДО и розничных облигаций (Сергиевское YTM 25,07% | Л-Старт YTM 32,53% | Идель Нефтемаш YTM 30,6% | БИЗНЕС АЛЬЯНС YTM 26,22%)
На 17 июня запланировано размещение облигаций растениеводческой компании ООО Сергиевское ( BB-.ru , 50 млн руб., ставка купона 23%, YTM...
Фото
Цена результата, о которой никто не рассказывает
Всем Привет, на связи Иван Кондратенко. Трейдер Проплайв/Prop Live и ведущий Трейдер ТВ. Сегодня поговорим о цене результата. О ней редко говорят...
Фото
Accent объявляет SPO фонда «Акцент 4»
Accent объявляет SPO фонда «Акцент 4»   Дополнительно будет выпущено 220 тыс. паев на сумму более 300 млн рублей. Прием...
Конспект Мозгового штурма. Инсайды с ПМЭФа. Weekly №120
Доброго дня дорогие товарищи. Сегодня у нас был традиционный мозговой штурм. Делюсь итогами штурма и инсайдами с ПМЭФа.

теги блога TaurusGOLD

....все тэги



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