Блог им. TaurusGOLD

Настройки - параметры инструментов и подключения
Котировки - текущие цены всех инструментов
Арбитраж - расчет спредов и сигналы
Торговля - отправка заявок
Портфель - мониторинг позиций
Графики - визуализация спредов
A1: "АРБИТРАЖ СБЕРБАНК - НАСТРОЙКИ" A3: "ИНСТРУМЕНТЫ АРБИТРАЖА" A4: "Тикер" B4: "Название" C4: "Класс" D4: "Тип" E4: "Лотность" A5: "SBER" B5: "Сбербанк ао" C5: "TQBR" D5: "Акция" E5: "10" A6: "SBERP" B6: "Сбербанк ап" C6: "TQBR" D6: "Акция" E6: "10" A7: "SRM3" B7: "Фьючерс Сбер" C7: "SPBFUT" D7: "Фьючерс" E7: "100" A9: "ПАРАМЕТРЫ АРБИТРАЖА" A10: "Исторический спред SBER/SBERP:" B10: "0.85" A11: "Стандартное отклонение:" B11: "0.05" A12: "Уровень входа (σ):" B12: "2" A13: "Уровень выхода (σ):" B13: "0.5" A14: "Объем сделки (лотов):" B14: "10" A16: "ПОДКЛЮЧЕНИЕ QUIK" A17: "DDE Service:" B17: "QLUA" A18: "DDE Topic:" B18: "QuikTrans2" A19: "Торговый счет:" B19: "L01-00000F00" <a name="cut"></a> <br /><br />
A1: "ТЕКУЩИЕ КОТИРОВКИ" A2: "Инструмент" B2: "Бид" C2: "Оффер" D2: "Послед." E2: "Время" F2: "Объем" A3: "SBER" A4: "SBERP" A5: "<span style="text-decoration: line-through;">SRM5</span>" A6: "Спред SBER/SBERP" A7: "Спред SBER/Фьючерс" A8: "Спред SBERP/Фьючерс"
A1: "РАСЧЕТ АРБИТРАЖНЫХ СПРЕДОВ" A2: "ПАРА" B2: "Текущий спред" C2: "Историч. среднее" D2: "Отклонение (σ)" E2: "Сигнал" F2: "Действие" A3: "SBER / SBERP" A4: "SBER / Фьючерс" A5: "SBERP / Фьючерс" A6: "Треугольный арбитраж" B7: "ВРЕМЯ ОБНОВЛЕНИЯ:" C7: "=NOW()" A9: "ОТКРЫТЫЕ ПОЗИЦИИ" A10: "Инструмент" B10: "Позиция" C10: "Средняя" D10: "P&L" E10: "Статус"
' Модуль арбитражной стратегии Сбербанк
Option Explicit
' Константы
Private Const QUIK_DDE_SERVICE As String = "QLUA"
Private Const QUIK_DDE_TOPIC As String = "QuikTrans2"
Private ddeChannel As Long
' Данные инструментов
Private Type InstrumentData
Ticker As String
ClassCode As String
BidPrice As Double
AskPrice As Double
LastPrice As Double
LotSize As Long
End Type
Dim instruments(1 To 3) As InstrumentData
' ==================== ИНИЦИАЛИЗАЦИЯ ====================
Public Sub InitializeArbitrage()
' Инициализация инструментов
InitializeInstruments
' Подключение к QUIK
ConnectToQUIK
' Первое обновление данных
UpdateAllData
End Sub
Private Sub InitializeInstruments()
With instruments(1)
.Ticker = "SBER"
.ClassCode = "TQBR"
.LotSize = 10
End With
With instruments(2)
.Ticker = "SBERP"
.ClassCode = "TQBR"
.LotSize = 10
End With
With instruments(3)
.Ticker = "SRM3"
.ClassCode = "SPBFUT"
.LotSize = 100
End With
End Sub
' ==================== РАСЧЕТ АРБИТРАЖНЫХ СПРЕДОВ ====================
Public Sub CalculateArbitrageSpreads()
Dim wsArb As Worksheet
Set wsArb = ThisWorkbook.Sheets("Арбитраж")
' Обновляем цены
UpdateAllPrices
' 1. Спред SBER / SBERP
Dim spread_SBER_SBERP As Double
If instruments(1).LastPrice > 0 And instruments(2).LastPrice > 0 Then
spread_SBER_SBERP = instruments(1).LastPrice / instruments(2).LastPrice
CalculateSBER_SBERP_Arbitrage spread_SBER_SBERP, wsArb
End If
' 2. Спред SBER / Фьючерс
If instruments(1).LastPrice > 0 And instruments(3).LastPrice > 0 Then
CalculateSBER_Futures_Arbitrage wsArb
End If
' 3. Треугольный арбитраж
CalculateTriangularArbitrage wsArb
' Обновляем время
wsArb.Range("C7").Value = Now
End Sub
' Арбитраж между обычными и привилегированными акциями
Private Sub CalculateSBER_SBERP_Arbitrage(ByVal currentSpread As Double, ws As Worksheet)
Dim histSpread As Double, stdDev As Double
Dim entryLevel As Double, exitLevel As Double
histSpread = ThisWorkbook.Sheets("Настройки").Range("B10").Value
stdDev = ThisWorkbook.Sheets("Настройки").Range("B11").Value
entryLevel = ThisWorkbook.Sheets("Настройки").Range("B12").Value
exitLevel = ThisWorkbook.Sheets("Настройки").Range("B13").Value
Dim deviation As Double
deviation = (currentSpread - histSpread) / stdDev
' Записываем данные
ws.Range("B3").Value = currentSpread
ws.Range("C3").Value = histSpread
ws.Range("D3").Value = deviation
' Определяем сигнал
If deviation > entryLevel Then
' SBER перекуплен относительно SBERP - продаем SBER, покупаем SBERP
ws.Range("E3").Value = "SELL SBER / BUY SBERP"
ws.Range("F3").Value = "ВХОД"
If CheckNoOpenPositions() Then
ExecuteSBER_SBERP_Arbitrage "SELL_BUY", currentSpread
End If
ElseIf deviation < -entryLevel Then
' SBER перепродан относительно SBERP - покупаем SBER, продаем SBERP
ws.Range("E3").Value = "BUY SBER / SELL SBERP"
ws.Range("F3").Value = "ВХОД"
If CheckNoOpenPositions() Then
ExecuteSBER_SBERP_Arbitrage "BUY_SELL", currentSpread
End If
ElseIf Abs(deviation) < exitLevel And CheckOpenPositions() Then
' Выход из позиции
ws.Range("E3").Value = "ЗАКРЫТИЕ"
ws.Range("F3").Value = "ВЫХОД"
CloseAllPositions
Else
ws.Range("E3").Value = "ОЖИДАНИЕ"
ws.Range("F3").Value = "НЕТ СИГНАЛА"
End If
' Раскрашиваем ячейку сигнала
If deviation > 1 Then
ws.Range("E3").Interior.Color = RGB(255, 200, 200) ' Красный
ElseIf deviation < -1 Then
ws.Range("E3").Interior.Color = RGB(200, 255, 200) ' Зеленый
Else
ws.Range("E3").Interior.Color = RGB(255, 255, 200) ' Желтый
End If
End Sub
' Арбитраж между акциями и фьючерсом
Private Sub CalculateSBER_Futures_Arbitrage(ws As Worksheet)
Dim futuresPrice As Double, spotPrice As Double
Dim theoreticalPrice As Double, actualPrice As Double
spotPrice = instruments(1).LastPrice
futuresPrice = instruments(3).LastPrice
' Теоретическая цена фьючерса (упрощенная формула)
Dim riskFreeRate As Double, daysToExpiry As Double
riskFreeRate = 0.08 ' 8% годовых
daysToExpiry = 90 ' дней до экспирации
theoreticalPrice = spotPrice * (1 + riskFreeRate * daysToExpiry / 365)
actualPrice = futuresPrice
Dim basis As Double
basis = actualPrice - theoreticalPrice
' Записываем данные
ws.Range("B4").Value = basis
ws.Range("C4").Value = 0 ' Теоретический базис должен быть 0
ws.Range("D4").Value = basis / (spotPrice * 0.01) ' В процентах от спота
If basis > spotPrice * 0.02 Then ' Базис > 2%
ws.Range("E4").Value = "BUY SBER / SELL FUTURES"
ws.Range("F4").Value = "ВХОД"
ElseIf basis < -spotPrice * 0.02 Then ' Базис < -2%
ws.Range("E4").Value = "SELL SBER / BUY FUTURES"
ws.Range("F4").Value = "ВХОД"
Else
ws.Range("E4").Value = "ОЖИДАНИЕ"
ws.Range("F4").Value = "НЕТ СИГНАЛА"
End If
End Sub
' Треугольный арбитраж
Private Sub CalculateTriangularArbitrage(ws As Worksheet)
Dim price_SBER As Double, price_SBERP As Double, price_FUT As Double
price_SBER = instruments(1).LastPrice
price_SBERP = instruments(2).LastPrice
price_FUT = instruments(3).LastPrice
If price_SBER > 0 And price_SBERP > 0 And price_FUT > 0 Then
' Проверяем различные комбинации
Dim arbOpportunity As String
arbOpportunity = CheckTriangularArbitrage(price_SBER, price_SBERP, price_FUT)
ws.Range("B5").Value = arbOpportunity
ws.Range("E5").Value = arbOpportunity
ws.Range("F5").Value = IIf(arbOpportunity = "НЕТ", "НЕТ СИГНАЛА", "ВХОД")
End If
End Sub
Private Function CheckTriangularArbitrage(SBER As Double, SBERP As Double, FUT As Double) As String
' Проверяем различные арбитражные возможности
Dim threshold As Double: threshold = 0.02 ' 2%
' SBER -> SBERP -> FUT -> SBER
Dim path1 As Double
path1 = (SBERP / SBER) * (FUT / SBERP) * (SBER / FUT)
If Abs(path1 - 1) > threshold Then
CheckTriangularArbitrage = "ТРЕУГОЛЬНЫЙ АРБИТРАЖ"
Exit Function
End If
CheckTriangularArbitrage = "НЕТ"
End Function
' ==================== ИСПОЛНЕНИЕ СДЕЛОК ====================
' Исполнение арбитража SBER/SBERP
Private Sub ExecuteSBER_SBERP_Arbitrage(direction As String, spread As Double)
Dim quantity As Long
quantity = ThisWorkbook.Sheets("Настройки").Range("B14").Value
Dim wsTrade As Worksheet
Set wsTrade = ThisWorkbook.Sheets("Торговля")
If direction = "BUY_SELL" Then
' Покупаем SBER, продаем SBERP
SendLimitOrder "SBER", "TQBR", "BUY", quantity, instruments(1).AskPrice
SendLimitOrder "SBERP", "TQBR", "SELL", quantity, instruments(2).BidPrice
' Логируем сделку
LogTrade "OPEN", "SBER/SBERP", "BUY_SELL", spread, quantity
ElseIf direction = "SELL_BUY" Then
' Продаем SBER, покупаем SBERP
SendLimitOrder "SBER", "TQBR", "SELL", quantity, instruments(1).BidPrice
SendLimitOrder "SBERP", "TQBR", "BUY", quantity, instruments(2).AskPrice
' Логируем сделку
LogTrade "OPEN", "SBER/SBERP", "SELL_BUY", spread, quantity
End If
End Sub
' Закрытие всех позиций
Private Sub CloseAllPositions()
' Получаем текущие позиции из портфеля
Dim wsPortfolio As Worksheet
Set wsPortfolio = ThisWorkbook.Sheets("Портфель")
' Закрываем позиции встречными сделками
' (реализация зависит от структуры данных портфеля)
UpdateStatus "Закрытие арбитражных позиций"
End Sub
' ==================== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ====================
' Проверка открытых позиций
Private Function CheckOpenPositions() As Boolean
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Портфель")
' Проверяем есть ли ненулевые позиции
CheckOpenPositions = (ws.Range("B11").Value <> 0 Or _
ws.Range("B12").Value <> 0 Or _
ws.Range("B13").Value <> 0)
End Function
Private Function CheckNoOpenPositions() As Boolean
CheckNoOpenPositions = Not CheckOpenPositions
End Function
' Логирование сделок
Private Sub LogTrade(action As String, pair As String, direction As String, _
spread As Double, quantity As Long)
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Торговля")
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
ws.Cells(lastRow, 1).Value = Now
ws.Cells(lastRow, 2).Value = action
ws.Cells(lastRow, 3).Value = pair
ws.Cells(lastRow, 4).Value = direction
ws.Cells(lastRow, 5).Value = spread
ws.Cells(lastRow, 6).Value = quantity
ws.Cells(lastRow, 7).Value = "АРБИТРАЖ"
End Sub
' Обновление всех цен
Private Sub UpdateAllPrices()
Dim i As Integer
For i = 1 To 3
UpdateInstrumentPrice i
Next i
End Sub
' Обновление цены инструмента
Private Sub UpdateInstrumentPrice(index As Integer)
With instruments(index)
.BidPrice = GetDDEValue(.Ticker, "BID")
.AskPrice = GetDDEValue(.Ticker, "OFFER")
.LastPrice = GetDDEValue(.Ticker, "LAST")
End With
End Sub
' ==================== ИНТЕРФЕЙС И УПРАВЛЕНИЕ ====================
' Запуск арбитражного робота
Public Sub StartArbitrageRobot()
InitializeArbitrage
UpdateStatus "Арбитражный робот запущен"
' Запускаем автоматическое обновление
Application.OnTime Now + TimeValue("00:00:05"), "ArbitrageUpdateCycle"
End Sub
' Цикл обновления арбитража
Public Sub ArbitrageUpdateCycle()
On Error GoTo ErrorHandler
CalculateArbitrageSpreads
UpdatePortfolioDisplay
' Следующее обновление через 10 секунд
Application.OnTime Now + TimeValue("00:00:10"), "ArbitrageUpdateCycle"
Exit Sub
ErrorHandler:
UpdateStatus "Ошибка в цикле арбитража: " & Err.Description
Application.OnTime Now + TimeValue("00:00:30"), "ArbitrageUpdateCycle"
End Sub
' Остановка робота
Public Sub StopArbitrageRobot()
On Error Resume Next
Application.OnTime EarliestTime:=Now + TimeValue("00:00:01"), _
Procedure:="ArbitrageUpdateCycle", Schedule:=False
UpdateStatus "Арбитражный робот остановлен"
End Sub
' Обновление отображения портфеля
Private Sub UpdatePortfolioDisplay()
Dim wsPortfolio As Worksheet
Set wsPortfolio = ThisWorkbook.Sheets("Портфель")
' Здесь можно добавить логику обновления позиций
' из QUIK через DDE запросы
End Sub
' Функции подключения к QUIK (аналогично предыдущему примеру)
Private Sub ConnectToQUIK()
' Реализация подключения к QUIK через DDE
End Sub
Private Function GetDDEValue(ticker As String, param As String) As Double
' Реализация получения данных через DDE
End Function
Private Sub SendLimitOrder(ticker As String, classCode As String, _
operation As String, quantity As Long, price As Double)
' Реализация отправки заявки
End Sub
Private Sub UpdateStatus(message As String)
ThisWorkbook.Sheets("Арбитраж").Range("A20").Value = message
End SubЗаполните настройки в соответствующем листе
Запустите подключение к QUIK
Включите арбитражного робота - StartArbitrageRobot
Следите за сигналами на листе «Арбитраж»
Робот автоматически будет входить и выходить из арбитражных сделок
SBER/SBERP - классический спред между акциями
Базисный арбитраж - акции vs фьючерс
Треугольный арбитраж - комбинация всех трех инструментов
Временной риск (несинхронное исполнение)
Ликвидность инструментов
Изменение дивидендной политики
Комиссии и проскальзывания
Тестируйте стратегию на исторических данных перед использованием!