В терминале QUIK доступно множество типов заявок, позволяющих гибко управлять позициями и автоматизировать торговлю. В этой статье мы разберем все виды заявок, ответим на частые вопросы трейдеров и приведем универсальный пример для программной установки через Lua-скрипты.
📌 Основные типы заявок
1️⃣ Лимитная заявка (limit)
Лимитная заявка — это ордер с заранее заданной ценой, по которой вы готовы совершить сделку. Она попадает в стакан заявок и ожидает встречного предложения. Используется для входа в рынок по указанной цене.
- Появляется в таблице «orders»
- Исполняется при достижении цены PRICE
- Может исполняться частично
2️⃣ Рыночная заявка (limit_market)
Рыночная заявка исполняется мгновенно по лучшей доступной цене. Для фьючерсов (SPBFUT) используется минимальная или максимальная цена.
- Появляется в таблице «orders»
- Исполняется мгновенно
- Не гарантирует точную цену входа
3️⃣ Стоп-лимит (stop-limit)
Стоп-лимит — заявка для входа в рынок на пробой уровня. При достижении цены активации выставляется лимитная заявка.
- Появляется в таблице «stop_orders»
- Для BUY: PRICE >= STOPPRICE
- Для SELL: PRICE <= STOPPRICE
4️⃣ Тейк-профит (take)
Тейк-профит — заявка для фиксации прибыли по открытой позиции. Работает по принципу «скользящего» ордера.
- Появляется в таблице «stop_orders»
- Требует номер активной базовой заявки (order_num)
- При достижении STOPPRICE и откате на OFFSET выставляется заявка
5️⃣ Комбинированная заявка (take-stop)
Тейк-профит и стоп-лимит — одна заявка управляет и тейком, и стопом. При срабатывании одного условия, второе автоматически отменяется.
- Появляется в таблице «stop_orders»
- MARKET_TAKE_PROFIT = YES (по умолчанию)
- Может быть с привязкой к базовой заявке или без
6️⃣ Тейк-профит для входа (take-entry)
Тейк-профит для входа — специальный тип для входа в рынок на отскоке. Не требует базовой заявки.
- Появляется в таблице «stop_orders»
- Не требует order_num
- Используется как TAKE_PROFIT_STOP_ORDER
🔍 Ответы на частые вопросы
❓ Можно ли выставить заявку на покупку/продажу с одновременной установкой стоп-лосса и тейк-профита одной заявкой?
Да, можно. В QUIK для этого существует тип заявки «Тейк-профит и стоп-лимит» (take-stop). Это условная заявка, которая одновременно задает оба уровня. Как только одно из условий сработает, второе автоматически отменяется системой.
❓ Где задается цена входа в такой заявке?
Цена входа задается отдельно. Сама стоп-заявка «Тейк-профит и стоп-лимит» не открывает позицию — она управляет уже открытой позицией. Цена входа — это параметр PRICE в лимитной заявке, которая открывает позицию. Стоп-заявка лишь автоматически управляет уже открытой позицией.
Последовательность действий:
- Выставляется лимитная заявка на вход (PRICE = цена входа)
- После ее исполнения выставляется стоп-заявка «Тейк-профит и стоп-лимит»
❓ Можно ли использовать заявку «Тейк-профит» для входа в рынок?
Да, можно. Для этого используется тип заявки TAKE_PROFIT_STOP_ORDER (в нашем коде — «take-entry»). В этом случае:
- Не требуется базовая заявка (order_num не нужен)
- Заявка появляется в таблице «stop_orders»
- При достижении STOPPRICE и откате на OFFSET выставляется заявка
Важно: Для входа на отскоке не используйте тип ACTIVATED_BY_ORDER_TAKE_PROFIT_STOP_ORDER — он предназначен только для уже открытых позиций и требует номера базовой заявки.
❓ Какие параметры нужны для комбинированной заявки (take-stop)?
Для заявки типа «take-stop» требуется следующий набор параметров:
local order_param = {
type_order = "take-stop",
take = 274.68, -- Тейк-профит
stop = 278.29, -- Стоп-лосс
volume = 1,
price = 272.00, -- Цена входа (для лимитной заявки)
comment = "TP_1_buy_270"
}
При этом в транзакцию передаются:
- STOPPRICE = take (цена активации тейк-профита)
- STOPPRICE2 = stop (цена активации стоп-лосса)
- PRICE = цена для лимитной заявки стоп-лосса
❓ Что делать, если возникает ошибка «Неправильно указан номер базовой заявки»?
Эта ошибка возникает, когда вы пытаетесь создать заявку типа ACTIVATED_BY_ORDER_TAKE_PROFIT_AND_STOP_LIMIT_ORDER (по исполнению), но базовая заявка уже исполнена.
Важное правило: Заявки «по исполнению» могут быть созданы только до исполнения базовой заявки. Как только базовая заявка получает статус «Исполнена», привязать к ней стоп-заявку уже невозможно.
Решение:
- Выставляйте стоп-заявку до исполнения базовой заявки
- Используйте OnOrder для получения номера базовой заявки (вместо OnTransReply)
- Если базовая заявка уже исполнена, используйте обычную заявку TAKE_PROFIT_AND_STOP_LIMIT_ORDER без BASE_ORDER_KEY
💻 Универсальный метод для установки заявок
Ниже приведен универсальный метод Transaction, который поддерживает все описанные типы заявок.
--=================================================================
-- УСТАНОВКА ЗАЯВКИ В СИСТЕМУ TRANSACTION
--
-- Параметры:
-- operation - тип операции: "buy" или "sell"
-- order_param - таблица с параметрами заявки:
-- volume - объем (обязательный)
-- comment - комментарий (макс 12 символов)
-- price - цена (для лимитных заявок)
-- last - цена последней сделки (для limit_market)
-- take - цена тейк-профита
-- stop - цена стоп-лосса
-- order_num - НОМЕР БАЗОВОЙ ЗАЯВКИ (для ACTIVATED_BY_ORDER)
-- ВНИМАНИЕ: базовая заявка ДОЛЖНА БЫТЬ АКТИВНОЙ!
--
-- type_order - тип заявки (обязательный):
--
-- === ДЛЯ ВХОДА В РЫНОК ===
-- "limit" - лимитная заявка по указанной цене
-- "limit_market" - рыночная заявка (исполняется мгновенно)
-- "stop-limit" - стоп-лимит на пробой уровня
--
-- === ДЛЯ УПРАВЛЕНИЯ ОТКРЫТЫМИ ПОЗИЦИЯМИ ===
-- "stop" - стоп-лосс (требует price)
-- "take" - тейк-профит (требует order_num - АКТИВНОЙ заявки!)
-- "take-stop" - комбинированная заявка (тейк + стоп)
-- Если order_num указан - используется как ACTIVATED_BY_ORDER
-- (базовая заявка должна быть АКТИВНОЙ!)
--
-- === ДЛЯ ВХОДА НА ОТСКОКЕ ===
-- "take-entry" - тейк-профит для входа в рынок (НЕ требует order_num)
--
-- Возвращаемые значения:
-- success (boolean) - true при успешной отправке
-- id_transact (number) - идентификатор транзакции
--=================================================================
function TransactionClass:Transaction(operation, order_param)
local func_name = ":Transaction"
-- Автокоррекция счета (L01-00000F00 вместо L01-0000F00)
if self.account and string.find(self.account, "L01") then
if string.match(self.account, "L01%-%d+") then
local num_part = string.match(self.account, "L01%-(%d+)")
if num_part and #num_part == 4 then
self.account = "L01-00000F00"
self.logging_obj:info(
string.format("Счет скорректирован: L01-0000F00 -> L01-00000F00"),
self.name_class .. func_name
)
end
end
end
-- Получаем ID транзакции
local id_transact = self:GetId()
-- Количество знаков после запятой
local digits_str = tostring(self.digits)
-- Логирование входных параметров
local msg = string.format("******************\nТаблица order_param")
self.logging_obj:info(msg, self.name_class .. func_name)
self.logging_obj:print_table(order_param, "order_param")
-- Формируем базовую таблицу транзакции
local transact_table = {
["TRANS_ID"] = id_transact,
["CLASSCODE"] = self.class,
["SECCODE"] = self.name,
["QUANTITY"] = string.format("%.0f", NumberClass.round(order_param.volume, 0)),
["ACCOUNT"] = self.account,
["CLIENT_CODE"] = order_param.comment or "",
["EXECUTION_CONDITION"] = "PUT_IN_QUEUE",
}
-- Определяем операцию
if operation == "sell" then
transact_table["OPERATION"] = "S"
else
transact_table["OPERATION"] = "B"
end
--=================================================================
-- ОБРАБОТКА ТИПОВ ЗАЯВОК
--=================================================================
-- 1. ЛИМИТНАЯ ЗАЯВКА (вход по указанной цене)
if order_param.type_order == "limit" then
transact_table["ACTION"] = "NEW_ORDER"
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.price, self.digits))
-- 2. ЛИМИТНАЯ ЗАЯВКА ПО РЫНОЧНОЙ ЦЕНЕ
elseif order_param.type_order == "limit_market" then
transact_table["ACTION"] = "NEW_ORDER"
transact_table["TYPE"] = "M"
if self.class == "SPBFUT" then
if operation == "sell" then
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(self:GetMinPrice(order_param.last), self.digits))
else
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(self:GetMaxPrice(order_param.last), self.digits))
end
else
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(0, self.digits))
end
-- 3. СТОП-ЛИМИТ (вход на пробой)
elseif order_param.type_order == "stop-limit" then
transact_table["ACTION"] = "NEW_STOP_ORDER"
transact_table["STOPPRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.price, self.digits))
if operation == "sell" then
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.price - self.offset * self.step_price, self.digits))
else
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.price + self.offset * self.step_price, self.digits))
end
-- 4. СТОП-ЛОСС (управление открытой позицией)
elseif order_param.type_order == "stop" then
transact_table["ACTION"] = "NEW_STOP_ORDER"
transact_table["STOP_ORDER_KIND"] = "STOP_LIMIT_ORDER"
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.price, self.digits))
transact_table["STOPPRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.stop, self.digits))
-- Если указан номер заявки-условия (должна быть АКТИВНОЙ!)
if order_param.order_num ~= nil then
transact_table["STOP_ORDER_KIND"] = "ACTIVATED_BY_ORDER_STOP_LIMIT_ORDER"
transact_table["BASE_ORDER_KEY"] = order_param.order_num
transact_table["USE_BASE_ORDER_BALANCE"] = "YES"
transact_table["ACTIVATE_IF_BASE_ORDER_PARTLY_FILLED"] = "YES"
end
-- 5. ТЕЙК-ПРОФИТ (управление открытой позицией)
-- ВНИМАНИЕ: ТРЕБУЕТСЯ активная базовая заявка (order_num)
elseif order_param.type_order == "take" then
transact_table["ACTION"] = "NEW_STOP_ORDER"
transact_table["STOP_ORDER_KIND"] = "ACTIVATED_BY_ORDER_TAKE_PROFIT_STOP_ORDER"
transact_table["BASE_ORDER_KEY"] = order_param.order_num
transact_table["USE_BASE_ORDER_BALANCE"] = "YES"
transact_table["ACTIVATE_IF_BASE_ORDER_PARTLY_FILLED"] = "YES"
-- Цена активации тейк-профита
transact_table["STOPPRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.take, self.digits))
-- Отступ (OFFSET) - для расчета отката
local offset_val = self.offset_take
if offset_val == 0 and self.step_price > 0 then
offset_val = self.step_price * 5
end
transact_table["OFFSET"] = string.format("%."..digits_str.."f",
NumberClass.round(offset_val, self.digits))
transact_table["OFFSET_UNITS"] = "PRICE_UNITS"
-- Защитный спред (SPREAD)
local spread_val = self.spread_take
if spread_val == 0 and self.step_price > 0 then
spread_val = self.step_price * 5
end
transact_table["SPREAD"] = string.format("%."..digits_str.."f",
NumberClass.round(spread_val, self.digits))
transact_table["SPREAD_UNITS"] = "PRICE_UNITS"
-- Рыночный тейк-профит по умолчанию
transact_table["MARKET_TAKE_PROFIT"] = "YES"
-- 6. КОМБИНИРОВАННАЯ ЗАЯВКА (тейк-профит + стоп-лосс)
-- Если указан order_num - используется как ACTIVATED_BY_ORDER (базовая заявка должна быть АКТИВНОЙ!)
-- Если order_num НЕ указан - работает как обычная TAKE_PROFIT_AND_STOP_LIMIT_ORDER
elseif order_param.type_order == "take-stop" then
transact_table["ACTION"] = "NEW_STOP_ORDER"
-- Если есть номер базовой заявки - используем тип "по исполнению"
if order_param.order_num ~= nil then
transact_table["STOP_ORDER_KIND"] = "ACTIVATED_BY_ORDER_TAKE_PROFIT_AND_STOP_LIMIT_ORDER"
transact_table["BASE_ORDER_KEY"] = order_param.order_num
transact_table["USE_BASE_ORDER_BALANCE"] = "YES"
transact_table["ACTIVATE_IF_BASE_ORDER_PARTLY_FILLED"] = "YES"
else
transact_table["STOP_ORDER_KIND"] = "TAKE_PROFIT_AND_STOP_LIMIT_ORDER"
end
-- Цена активации тейк-профита
transact_table["STOPPRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.take, self.digits))
-- Цена активации стоп-лосса
transact_table["STOPPRICE2"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.stop, self.digits))
-- Цена для лимитной заявки стоп-лосса
if operation == "sell" then
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.stop + self.offset * self.step_price, self.digits))
else
transact_table["PRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.stop - self.offset * self.step_price, self.digits))
end
-- Отступ для тейк-профита
local offset_val = self.offset_take
if offset_val == 0 and self.step_price > 0 then
offset_val = self.step_price * 5
end
transact_table["OFFSET"] = string.format("%."..digits_str.."f",
NumberClass.round(offset_val, self.digits))
transact_table["OFFSET_UNITS"] = "PRICE_UNITS"
-- Защитный спред
local spread_val = self.spread_take
if spread_val == 0 and self.step_price > 0 then
spread_val = self.step_price * 5
end
transact_table["SPREAD"] = string.format("%."..digits_str.."f",
NumberClass.round(spread_val, self.digits))
transact_table["SPREAD_UNITS"] = "PRICE_UNITS"
-- Используем рыночный тейк-профит по умолчанию
transact_table["MARKET_TAKE_PROFIT"] = "YES"
transact_table["MARKET_STOP_LIMIT"] = "NO"
-- 7. ТЕЙК-ПРОФИТ ДЛЯ ВХОДА В РЫНОК (на отскоке)
-- НЕ требует базовой заявки (order_num не используется)
elseif order_param.type_order == "take-entry" then
transact_table["ACTION"] = "NEW_STOP_ORDER"
transact_table["STOP_ORDER_KIND"] = "TAKE_PROFIT_STOP_ORDER"
-- Цена активации тейк-профита (уровень для входа)
transact_table["STOPPRICE"] = string.format("%."..digits_str.."f",
NumberClass.round(order_param.take, self.digits))
-- Отступ (OFFSET)
local offset_val = self.offset_take
if offset_val == 0 and self.step_price > 0 then
offset_val = self.step_price * 5
end
transact_table["OFFSET"] = string.format("%."..digits_str.."f",
NumberClass.round(offset_val, self.digits))
transact_table["OFFSET_UNITS"] = "PRICE_UNITS"
-- Защитный спред (SPREAD)
local spread_val = self.spread_take
if spread_val == 0 and self.step_price > 0 then
spread_val = self.step_price * 5
end
transact_table["SPREAD"] = string.format("%."..digits_str.."f",
NumberClass.round(spread_val, self.digits))
transact_table["SPREAD_UNITS"] = "PRICE_UNITS"
-- Рыночный тейк-профит по умолчанию
transact_table["MARKET_TAKE_PROFIT"] = "YES"
end
-- Логирование финальной таблицы транзакции
self.logging_obj:info("******************\nТаблица transact_table", self.name_class .. func_name)
self.logging_obj:print_table(transact_table, "transact_table")
self.logging_obj:info("******************", self.name_class .. func_name)
-- Получаем количество заявок до отправки
local num_orders = getNumberOf("orders") + getNumberOf("stop_orders")
-- Отправляем транзакцию
local error_transaction = sendTransaction(transact_table)
if error_transaction ~= "" then
self.logging_obj:error(
string.format("%s Ошибка '%s' при выставлении заявки '%s' '%s' на объем %f",
self.name, error_transaction, order_param.type_order, operation, order_param.volume),
self.name_class .. func_name
)
return false, 0
else
-- Проверяем, что заявка действительно появилась
sleep(500)
local num_orders_curr = getNumberOf("orders") + getNumberOf("stop_orders")
if num_orders_curr <= num_orders then
self.logging_obj:error(
string.format("%s Требуется проверка установки заявки '%s' '%s' (ID: %d)",
self.name, order_param.type_order, operation, id_transact),
self.name_class .. func_name
)
return false, 0
end
self.logging_obj:info(
string.format("%s Успешно отправлена заявка '%s' '%s' (ID: %d)",
self.name, order_param.type_order, operation, id_transact),
self.name_class .. func_name
)
return true, id_transact
end
end
📝 Примеры вызова функции
🔹 Вход в рынок по лимитной заявке
local order_param = {
type_order = "limit",
price = 100.50,
volume = 1,
comment = "TP_1_buy_100.50"
}
local success, id = transaction_obj:Transaction("buy", order_param)
🔹 Вход на отскоке через тейк-профит
local order_param = {
type_order = "take-entry",
take = 105.00, -- Уровень для входа
volume = 1,
comment = "TP_2_buy_105"
}
local success, id = transaction_obj:Transaction("buy", order_param)
🔹 Комбинированная заявка для открытой позиции
local order_param = {
type_order = "take-stop",
take = 105.00, -- Тейк-профит
stop = 95.00, -- Стоп-лосс
price = 100.00, -- Цена входа
volume = 1,
comment = "TP_3_buy_100",
order_num = 1234567 -- Номер АКТИВНОЙ базовой заявки
}
local success, id = transaction_obj:Transaction("sell", order_param)
🔹 Восстановление комбинированной заявки (без привязки)
-- Используется, когда базовая заявка уже исполнена
local order_param = {
type_order = "take-stop",
take = 105.00,
stop = 95.00,
price = 100.00,
volume = 1,
comment = "TP_3_buy_100"
-- order_num не передается!
}
local success, id = transaction_obj:Transaction("sell", order_param)
🎯 Ключевые выводы
- Для входа в рынок используйте типы: «limit», «limit_market», «stop-limit» или «take-entry»
- Для управления позицией используйте типы: «take», «stop» или «take-stop»
- Заявки «по исполнению» (ACTIVATED_BY_ORDER) требуют АКТИВНУЮ базовую заявку
- order_num должен быть получен ДО исполнения базовой заявки (через OnOrder)
- Если базовая заявка уже исполнена — используйте обычную заявку без BASE_ORDER_KEY
- Комбинированная заявка (take-stop) устанавливается одной транзакцией и управляет и тейком, и стопом




Добавить комментарий