Простой торговый робот по скользящей средней — различия между версиями
Админ (обсуждение | вклад) (Новая страница: «== Описание == Робот торгует по 2-м простым скользящим средним (MA), выставляет тэйк-профит и…») |
Админ (обсуждение | вклад) м (→Код) |
||
Строка 20: | Строка 20: | ||
== Код == | == Код == | ||
− | --[[ Простой MA-робот (c)QuikLuaCSharp.ru | + | --[[ Простой MA-робот (c)QuikLuaCSharp.ru |
− | !!! ДЛЯ ИСПОЛЬЗОВАНИЯ ТОЛЬКО В ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЯХ НА ДЕМО-СЧЕТЕ !!! | + | !!! ДЛЯ ИСПОЛЬЗОВАНИЯ ТОЛЬКО В ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЯХ НА ДЕМО-СЧЕТЕ !!! |
− | Робот торгует по 2-м простым(simple) скользящим средним (MA). | + | Робот торгует по 2-м простым(simple) скользящим средним (MA). |
− | 1.Если нет открытых роботом позиций выполняется следующий алгоритм: | + | 1.Если нет открытых роботом позиций выполняется следующий алгоритм: |
1.Если быстрая скользящая пересекает медленную снизу вверх и на текущей свече еще не открывались позиции, совершается покупка. | 1.Если быстрая скользящая пересекает медленную снизу вверх и на текущей свече еще не открывались позиции, совершается покупка. | ||
2.Если быстрая скользящая пересекает медленную сверху вниз и на текущей свече еще не открывались позиции, совершается продажа. | 2.Если быстрая скользящая пересекает медленную сверху вниз и на текущей свече еще не открывались позиции, совершается продажа. | ||
− | 2.Если открылась позиция, выставляется "Тэйк-профит и Стоп-лимит" | + | 2.Если открылась позиция, выставляется "Тэйк-профит и Стоп-лимит" |
− | 3.Робот ждет, пока закроется позичия по Стоп-лоссу, либо Тэйк-профиту, после чего переходит к пункту №1 | + | 3.Робот ждет, пока закроется позичия по Стоп-лоссу, либо Тэйк-профиту, после чего переходит к пункту №1 |
− | Особенности: | + | Особенности: |
− | 1.Робот выводит в текстовых сообщениях информацию о ключевых моментах алгоритма, у всех его сообщений префикс "Простой MA-робот:". | + | 1.Робот выводит в текстовых сообщениях информацию о ключевых моментах алгоритма, у всех его сообщений префикс "Простой MA-робот:". |
− | 2.Робот всегда находится в 1-м из 2-х состояний(ROBOT_STATE):'В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'. | + | 2.Робот всегда находится в 1-м из 2-х состояний(ROBOT_STATE):'В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'. |
− | 3.Если при выставлении заявки на продажу робот узнает, что операции шорт запрещены по данному инструменту, он больше не будет открывать шорт, только лонг. | + | 3.Если при выставлении заявки на продажу робот узнает, что операции шорт запрещены по данному инструменту, он больше не будет открывать шорт, только лонг. |
− | 4.Когда робот получает сигнал на открытие сделки, он совершает 10 попыток с прмежутками в 100 мс открыть позицию, если этого не удается, останавливает скрипт. | + | 4.Когда робот получает сигнал на открытие сделки, он совершает 10 попыток с прмежутками в 100 мс открыть позицию, если этого не удается, останавливает скрипт. |
− | 5.После открытия позиции робот совершает 10 попыток с прмежутками в 100 мс выставить Тэйк-профит и Стоп-лимит, а затем дождаться закрытия позиции, | + | 5.После открытия позиции робот совершает 10 попыток с прмежутками в 100 мс выставить Тэйк-профит и Стоп-лимит, а затем дождаться закрытия позиции, |
если этого не удается, останавливает скрипт. | если этого не удается, останавливает скрипт. | ||
− | 6.Если стоп-заявка сработала, но позиция не закрылась в течении 10 секунд, пытается за 10 попыток принудительно закрыть позицию встречной сделкой. | + | 6.Если стоп-заявка сработала, но позиция не закрылась в течении 10 секунд, пытается за 10 попыток принудительно закрыть позицию встречной сделкой. |
Если позицию удалось закрыть (даже принудительно), продолжает работать, иначе скрипт останавливается. | Если позицию удалось закрыть (даже принудительно), продолжает работать, иначе скрипт останавливается. | ||
− | ]] | + | ]] |
− | --/*НАСТРАИВАЕМЫЕ ПАРАМЕТРЫ*/ | + | --/*НАСТРАИВАЕМЫЕ ПАРАМЕТРЫ*/ |
− | --ACCOUNT = 'NL0011100043'; -- Идентификатор счета | + | --ACCOUNT = 'NL0011100043'; -- Идентификатор счета |
− | ACCOUNT = 'SPBFUT00506'; -- Идентификатор счета | + | ACCOUNT = 'SPBFUT00506'; -- Идентификатор счета |
− | --CLASS_CODE = 'QJSIM'; -- Код класса | + | --CLASS_CODE = 'QJSIM'; -- Код класса |
− | CLASS_CODE = 'SPBFUT'; -- Код класса | + | CLASS_CODE = 'SPBFUT'; -- Код класса |
− | --SEC_CODE = 'SBER'; -- Код бумаги | + | --SEC_CODE = 'SBER'; -- Код бумаги |
− | SEC_CODE = 'RIZ5'; -- Код бумаги | + | SEC_CODE = 'RIZ5'; -- Код бумаги |
− | INTERVAL = INTERVAL_M1; -- Таймфрейм графика (для построения скользящих) | + | INTERVAL = INTERVAL_M1; -- Таймфрейм графика (для построения скользящих) |
− | SLOW_MA_PERIOD = 12; -- ПЕРИОД МЕДЛЕННОЙ скользящей | + | SLOW_MA_PERIOD = 12; -- ПЕРИОД МЕДЛЕННОЙ скользящей |
− | SLOW_MA_SOURCE = 'C'; -- ИСТОЧНИК МЕДЛЕННОЙ скользящей [O - open, C - close, H - hi, L - low] | + | SLOW_MA_SOURCE = 'C'; -- ИСТОЧНИК МЕДЛЕННОЙ скользящей [O - open, C - close, H - hi, L - low] |
− | FAST_MA_PERIOD = 4; -- ПЕРИОД БЫСТРОЙ скользящей | + | FAST_MA_PERIOD = 4; -- ПЕРИОД БЫСТРОЙ скользящей |
− | FAST_MA_SOURCE = 'C'; -- ИСТОЧНИК БЫСТРОЙ скользящей [O - open, C - close, H - hi, L - low] | + | FAST_MA_SOURCE = 'C'; -- ИСТОЧНИК БЫСТРОЙ скользящей [O - open, C - close, H - hi, L - low] |
− | STOP_LOSS = 10; -- Размер СТОП-ЛОССА (в шагах цены) | + | STOP_LOSS = 10; -- Размер СТОП-ЛОССА (в шагах цены) |
− | TAKE_PROFIT = 30; -- Размер ТЭЙК-ПРОФИТА (в шагах цены) | + | TAKE_PROFIT = 30; -- Размер ТЭЙК-ПРОФИТА (в шагах цены) |
− | --/*РАБОЧИЕ ПЕРЕМЕННЫЕ РОБОТА (менять не нужно)*/ | + | --/*РАБОЧИЕ ПЕРЕМЕННЫЕ РОБОТА (менять не нужно)*/ |
− | SEC_PRICE_STEP = 0; -- ШАГ ЦЕНЫ ИНСТРУМЕНТА | + | SEC_PRICE_STEP = 0; -- ШАГ ЦЕНЫ ИНСТРУМЕНТА |
− | SEC_NO_SHORT = false; -- Флаг, что по данному инструменту запрещены операции шорт | + | SEC_NO_SHORT = false; -- Флаг, что по данному инструменту запрещены операции шорт |
− | DS = nil; -- Источник данных графика (DataSource) | + | DS = nil; -- Источник данных графика (DataSource) |
− | ROBOT_STATE ='В ПОИСКЕ ТОЧКИ ВХОДА';-- СОСТОЯНИЕ робота ['В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'] | + | ROBOT_STATE ='В ПОИСКЕ ТОЧКИ ВХОДА';-- СОСТОЯНИЕ робота ['В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'] |
− | trans_id = os.time(); -- Задает начальный номер ID транзакций | + | trans_id = os.time(); -- Задает начальный номер ID транзакций |
− | trans_Status = nil; -- Статус текущей транзакции из функции OnTransPeply | + | trans_Status = nil; -- Статус текущей транзакции из функции OnTransPeply |
− | trans_result_msg = ''; -- Сообщение по текущей транзакции из функции OnTransPeply | + | trans_result_msg = ''; -- Сообщение по текущей транзакции из функции OnTransPeply |
− | CurrentDirect = 'BUY'; -- Текущее НАПРАВЛЕНИЕ ['BUY', или 'SELL'] | + | CurrentDirect = 'BUY'; -- Текущее НАПРАВЛЕНИЕ ['BUY', или 'SELL'] |
− | LastOpenBarIndex = 0; -- Индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще одну позицию) | + | LastOpenBarIndex = 0; -- Индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще |
+ | одну позицию) | ||
− | Run = true; -- Флаг поддержания работы бесконечного цикла в main | + | Run = true; -- Флаг поддержания работы бесконечного цикла в main |
− | -- Функция первичной инициализации скрипта (ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK в самом начале) | + | -- Функция первичной инициализации скрипта (ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK в самом начале) |
− | function OnInit() | + | function OnInit() |
-- Получает доступ к свечам графика | -- Получает доступ к свечам графика | ||
local Error = ''; | local Error = ''; | ||
Строка 85: | Строка 86: | ||
-- Получает ШАГ ЦЕНЫ ИНСТРУМЕНТА | -- Получает ШАГ ЦЕНЫ ИНСТРУМЕНТА | ||
SEC_PRICE_STEP = getParamEx(CLASS_CODE, SEC_CODE, "SEC_PRICE_STEP").param_value; | SEC_PRICE_STEP = getParamEx(CLASS_CODE, SEC_CODE, "SEC_PRICE_STEP").param_value; | ||
− | end; | + | end; |
− | function main() | + | function main() |
-- Выводит сообщение | -- Выводит сообщение | ||
message('Простой MA-робот: '..ROBOT_STATE); | message('Простой MA-робот: '..ROBOT_STATE); | ||
Строка 195: | Строка 196: | ||
sleep(10);--Пауза 10 мс, для того, чтобы не перегружать процессор компьютера | sleep(10);--Пауза 10 мс, для того, чтобы не перегружать процессор компьютера | ||
end; | end; | ||
− | end; | + | end; |
− | -- Функция вызывается терминалом QUIK при получении ответа на транзакцию пользователя | + | -- Функция вызывается терминалом QUIK при получении ответа на транзакцию пользователя |
− | function OnTransReply(trans_reply) | + | function OnTransReply(trans_reply) |
-- Если поступила информация по текущей транзакции | -- Если поступила информация по текущей транзакции | ||
if trans_reply.trans_id == trans_id then | if trans_reply.trans_id == trans_id then | ||
Строка 206: | Строка 207: | ||
trans_result_msg = trans_reply.result_msg; | trans_result_msg = trans_reply.result_msg; | ||
end; | end; | ||
− | end; | + | end; |
− | -- Функция ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK при остановке скрипта | + | -- Функция ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK при остановке скрипта |
− | function OnStop() | + | function OnStop() |
Run = false; | Run = false; | ||
− | end; | + | end; |
− | ----------------------------- | + | ----------------------------- |
− | -- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ -- | + | -- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ -- |
− | ----------------------------- | + | ----------------------------- |
− | -- Совершает СДЕЛКУ указанного типа (Type) ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот, | + | -- Совершает СДЕЛКУ указанного типа (Type) ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот, |
− | --- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку | + | --- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку |
− | function Trade(Type) | + | function Trade(Type) |
--Получает ID транзакции | --Получает ID транзакции | ||
trans_id = trans_id + 1; | trans_id = trans_id + 1; | ||
Строка 227: | Строка 228: | ||
--Устанавливает цену и операцию, в зависимости от типа сделки и от класса инструмента | --Устанавливает цену и операцию, в зависимости от типа сделки и от класса инструмента | ||
if Type == 'BUY' then | if Type == 'BUY' then | ||
− | if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'offer').param_value + 10*SEC_PRICE_STEP;end; -- по цене, завышенной на 10 мин. шагов цены | + | if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'offer').param_value + 10*SEC_PRICE_STEP;end; -- по цене, завышенной на |
+ | 10 мин. шагов цены | ||
Operation = 'B'; | Operation = 'B'; | ||
else | else | ||
− | if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'bid').param_value - 10*SEC_PRICE_STEP;end; -- по цене, заниженной на 10 мин. шагов цены | + | if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'bid').param_value - 10*SEC_PRICE_STEP;end; -- по цене, заниженной на 10 |
+ | мин. шагов цены | ||
Operation = 'S'; | Operation = 'S'; | ||
end; | end; | ||
Строка 317: | Строка 320: | ||
end; | end; | ||
end; | end; | ||
− | end; | + | end; |
− | -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ переданного типа (Type) ["BUY", или "SELL"] | + | -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ переданного типа (Type) ["BUY", или "SELL"] |
− | function KillPos(Type) | + | function KillPos(Type) |
-- Дается 10 попыток | -- Дается 10 попыток | ||
local Count = 0; -- Счетчик попыток | local Count = 0; -- Счетчик попыток | ||
Строка 348: | Строка 351: | ||
-- Возвращает TRUE, если удалось принудительно закрыть позицию | -- Возвращает TRUE, если удалось принудительно закрыть позицию | ||
return true; | return true; | ||
− | end; | + | end; |
− | -- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ (Price) и ТИП (Type) ["BUY", или "SELL"] открытой сделки, | + | -- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ (Price) и ТИП (Type) ["BUY", или "SELL"] открытой сделки, |
− | --- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, либо TRUE, если сделка закрылась, | + | --- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, либо TRUE, если сделка закрылась, |
− | --- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию | + | --- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию |
− | function SL_TP(Price, Type) | + | function SL_TP(Price, Type) |
-- ID транзакции | -- ID транзакции | ||
trans_id = trans_id + 1; | trans_id = trans_id + 1; | ||
Строка 368: | Строка 371: | ||
-- Если не акции | -- Если не акции | ||
if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then | if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then | ||
− | price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMIN').param_value)); -- Цена выставляемой заявки после страбатывания Стопа минимально возможная, чтобы не проскользнуло | + | price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMIN').param_value)); -- Цена выставляемой заявки после страбатывания Стопа минимально возможная, |
+ | чтобы не проскользнуло | ||
market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене | market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене | ||
end; | end; | ||
Строка 377: | Строка 381: | ||
-- Если не акции | -- Если не акции | ||
if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then | if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then | ||
− | price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMAX').param_value)); -- Цена выставляемой заявки после страбатывания Стопа максимально возможная, чтобы не проскользнуло | + | price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMAX').param_value)); -- Цена выставляемой заявки после страбатывания Стопа максимально возможная, |
+ | чтобы не проскользнуло | ||
market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене | market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене | ||
end; | end; | ||
Строка 483: | Строка 488: | ||
end; | end; | ||
end; | end; | ||
− | end; | + | end; |
− | -- Возвращает ЗНАЧЕНИЕ МЕДЛЕННОЙ скользящей по индексу свечи (по умолчанию: последняя) | + | -- Возвращает ЗНАЧЕНИЕ МЕДЛЕННОЙ скользящей по индексу свечи (по умолчанию: последняя) |
− | function SlowMA(Index) | + | function SlowMA(Index) |
-- Если индекс свечи не указан, то устанавливает индекс последней свечи | -- Если индекс свечи не указан, то устанавливает индекс последней свечи | ||
if Index == nil then Index = DS:Size(); end; | if Index == nil then Index = DS:Size(); end; | ||
Строка 510: | Строка 515: | ||
-- Возвращает значение | -- Возвращает значение | ||
return Sum/SLOW_MA_PERIOD; | return Sum/SLOW_MA_PERIOD; | ||
− | end; | + | end; |
− | -- Возвращает ЗНАЧЕНИЕ БЫСТРОЙ скользящей по индексу свечи (по умолчанию: последняя) | + | -- Возвращает ЗНАЧЕНИЕ БЫСТРОЙ скользящей по индексу свечи (по умолчанию: последняя) |
− | function FastMA(Index) | + | function FastMA(Index) |
-- Если индекс свечи не указан, то устанавливает индекс последней свечи | -- Если индекс свечи не указан, то устанавливает индекс последней свечи | ||
if Index == nil then Index = DS:Size(); end; | if Index == nil then Index = DS:Size(); end; | ||
Строка 536: | Строка 541: | ||
-- Возвращает значение | -- Возвращает значение | ||
return Sum/FAST_MA_PERIOD; | return Sum/FAST_MA_PERIOD; | ||
− | end; | + | end; |
− | -- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil | + | -- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil |
− | function CheckBit(flags, bit) | + | function CheckBit(flags, bit) |
-- Проверяет, что переданные аргументы являются числами | -- Проверяет, что переданные аргументы являются числами | ||
if type(flags) ~= "number" then error("Предупреждение!!! Checkbit: 1-й аргумент не число!"); end; | if type(flags) ~= "number" then error("Предупреждение!!! Checkbit: 1-й аргумент не число!"); end; | ||
Строка 558: | Строка 563: | ||
else return nil; | else return nil; | ||
end; | end; | ||
− | end; | + | end; |
+ | |||
== См. также == | == См. также == | ||
* [[Торговый робот с приоритетами обработки потоков (заготовка)]] | * [[Торговый робот с приоритетами обработки потоков (заготовка)]] |
Версия 12:29, 6 апреля 2020
Содержание
Описание
Робот торгует по 2-м простым скользящим средним (MA), выставляет тэйк-профит и стоп-лимит.
- Если нет открытых роботом позиций выполняется следующий алгоритм:
- Если быстрая скользящая пересекает медленную снизу вверх и на текущей свече еще не открывались позиции, совершается покупка.
- Если быстрая скользящая пересекает медленную сверху вниз и на текущей свече еще не открывались позиции, совершается продажа.
- Если открылась позиция, выставляется "Тэйк-профит и Стоп-лимит"
- Робот ждет, пока закроется позиция по Стоп-лоссу, либо Тэйк-профиту, после чего переходит к пункту №1
Особенности:
1. Робот выводит в текстовых сообщениях информацию о ключевых моментах алгоритма, у всех его сообщений префикс "Простой MA-робот:". 2. Робот всегда находится в 1-м из 2-х состояний(ROBOT_STATE):'В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'. 3. Если при выставлении заявки на продажу робот узнает, что операции шорт запрещены по данному инструменту, он больше не будет открывать шорт, только лонг. 4. Когда робот получает сигнал на открытие сделки, он совершает 10 попыток с прмежутками в 100 мс открыть позицию, если этого не удается, останавливает скрипт. 5. После открытия позиции робот совершает 10 попыток с прмежутками в 100 мс выставить Тэйк-профит и Стоп-лимит, а затем дождаться закрытия позиции, если этого не удается, останавливает скрипт. 6. Если стоп-заявка сработала, но позиция не закрылась в течении 10 секунд, пытается за 10 попыток принудительно закрыть позицию встречной сделкой.
Если позицию удалось закрыть (даже принудительно), продолжает работать, иначе скрипт останавливается.
Код
--[[ Простой MA-робот (c)QuikLuaCSharp.ru !!! ДЛЯ ИСПОЛЬЗОВАНИЯ ТОЛЬКО В ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЯХ НА ДЕМО-СЧЕТЕ !!! Робот торгует по 2-м простым(simple) скользящим средним (MA). 1.Если нет открытых роботом позиций выполняется следующий алгоритм: 1.Если быстрая скользящая пересекает медленную снизу вверх и на текущей свече еще не открывались позиции, совершается покупка. 2.Если быстрая скользящая пересекает медленную сверху вниз и на текущей свече еще не открывались позиции, совершается продажа. 2.Если открылась позиция, выставляется "Тэйк-профит и Стоп-лимит" 3.Робот ждет, пока закроется позичия по Стоп-лоссу, либо Тэйк-профиту, после чего переходит к пункту №1 Особенности: 1.Робот выводит в текстовых сообщениях информацию о ключевых моментах алгоритма, у всех его сообщений префикс "Простой MA-робот:". 2.Робот всегда находится в 1-м из 2-х состояний(ROBOT_STATE):'В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'. 3.Если при выставлении заявки на продажу робот узнает, что операции шорт запрещены по данному инструменту, он больше не будет открывать шорт, только лонг. 4.Когда робот получает сигнал на открытие сделки, он совершает 10 попыток с прмежутками в 100 мс открыть позицию, если этого не удается, останавливает скрипт. 5.После открытия позиции робот совершает 10 попыток с прмежутками в 100 мс выставить Тэйк-профит и Стоп-лимит, а затем дождаться закрытия позиции, если этого не удается, останавливает скрипт. 6.Если стоп-заявка сработала, но позиция не закрылась в течении 10 секунд, пытается за 10 попыток принудительно закрыть позицию встречной сделкой. Если позицию удалось закрыть (даже принудительно), продолжает работать, иначе скрипт останавливается. ]] --/*НАСТРАИВАЕМЫЕ ПАРАМЕТРЫ*/ --ACCOUNT = 'NL0011100043'; -- Идентификатор счета ACCOUNT = 'SPBFUT00506'; -- Идентификатор счета --CLASS_CODE = 'QJSIM'; -- Код класса CLASS_CODE = 'SPBFUT'; -- Код класса --SEC_CODE = 'SBER'; -- Код бумаги SEC_CODE = 'RIZ5'; -- Код бумаги INTERVAL = INTERVAL_M1; -- Таймфрейм графика (для построения скользящих) SLOW_MA_PERIOD = 12; -- ПЕРИОД МЕДЛЕННОЙ скользящей SLOW_MA_SOURCE = 'C'; -- ИСТОЧНИК МЕДЛЕННОЙ скользящей [O - open, C - close, H - hi, L - low] FAST_MA_PERIOD = 4; -- ПЕРИОД БЫСТРОЙ скользящей FAST_MA_SOURCE = 'C'; -- ИСТОЧНИК БЫСТРОЙ скользящей [O - open, C - close, H - hi, L - low] STOP_LOSS = 10; -- Размер СТОП-ЛОССА (в шагах цены) TAKE_PROFIT = 30; -- Размер ТЭЙК-ПРОФИТА (в шагах цены) --/*РАБОЧИЕ ПЕРЕМЕННЫЕ РОБОТА (менять не нужно)*/ SEC_PRICE_STEP = 0; -- ШАГ ЦЕНЫ ИНСТРУМЕНТА SEC_NO_SHORT = false; -- Флаг, что по данному инструменту запрещены операции шорт DS = nil; -- Источник данных графика (DataSource) ROBOT_STATE ='В ПОИСКЕ ТОЧКИ ВХОДА';-- СОСТОЯНИЕ робота ['В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'] trans_id = os.time(); -- Задает начальный номер ID транзакций trans_Status = nil; -- Статус текущей транзакции из функции OnTransPeply trans_result_msg = ; -- Сообщение по текущей транзакции из функции OnTransPeply CurrentDirect = 'BUY'; -- Текущее НАПРАВЛЕНИЕ ['BUY', или 'SELL'] LastOpenBarIndex = 0; -- Индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще одну позицию) Run = true; -- Флаг поддержания работы бесконечного цикла в main -- Функция первичной инициализации скрипта (ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK в самом начале) function OnInit() -- Получает доступ к свечам графика local Error = ; DS,Error = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL); -- Если график, к которому нужно подключиться не открыт в терминале, то данные заказываются с сервера, на их получение нужно время, -- по этому, рекомендуется добавлять вот такое ожидание, прежде, чем обращаться к DS: -- Ждет, пока данные будут получены с сервера (на случай, если такой график не открыт) while (Error == "" or Error == nil) and DS:Size() == 0 do sleep(1) end if Error ~= "" and Error ~= nil then message("Ошибка подключения к графику: "..Error) return end -- Подписывается на обновления графика DS:SetEmptyCallback() -- Получает ШАГ ЦЕНЫ ИНСТРУМЕНТА SEC_PRICE_STEP = getParamEx(CLASS_CODE, SEC_CODE, "SEC_PRICE_STEP").param_value; end; function main() -- Выводит сообщение message('Простой MA-робот: '..ROBOT_STATE); -- "Бесконечный" цикл while Run do --Если СОСТОЯНИЕ робота "В ПРОЦЕССЕ СДЕЛКИ" if ROBOT_STATE == 'В ПРОЦЕССЕ СДЕЛКИ' then -- Выводит сообщение message('Простой MA-робот: В ПРОЦЕССЕ СДЕЛКИ'); -- Делает 10 попыток открыть сделку local Price = false; -- Переменная для получения результата открытия позиции (цена, либо ошибка(false)) for i=1,10 do if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс -- Если первый раз пытается открыть SELL, а операции шорт по данному инструменту запрещены if CurrentDirect == "SELL" and SEC_NO_SHORT then -- Прерывает цикл FOR break; end; -- Совершает СДЕЛКУ указанного типа ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот, --- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку Price = Trade(CurrentDirect); -- Если сделка открылась if Price ~= false then -- Прерывает цикл FOR break; end; sleep(100); -- Пауза в 100 мс между попытками открыть сделку end; if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс -- Если сделка открыта if Price ~= false then -- Запоминает индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще одну позицию) LastOpenBarIndex = DS:Size(); -- Выводит сообщение message('Простой MA-робот: Открыта сделка '..CurrentDirect..' по цене '..Price); -- Делает 10 попыток выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, и дождаться закрытия сделки message('Простой MA-робот: Делает 10 попыток выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, и дождаться закрытия сделки'); local Result = nil; -- Переменная для получения результата выставления и срабатывания СТОП-ЛОСС и ТЭЙК-ПРОФИТ for i=1,10 do if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс -- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ и ТИП ["BUY", или "SELL"] открытой сделки, --- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, или TRUE, если сделка закрылась, --- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию Result = SL_TP(Price, CurrentDirect); -- Если сделка закрылась if Result == true then -- Прерывает цикл FOR break; end; end; -- Если за 10 попыток не удалось закрыть позицию if Result == nil or Result == false then -- Выводит сообщение message('Простой MA-робот: После 10-и попыток не удалось закрыть сделку!!! Завершение скрипта!!!'); -- Завершает выполнение скрипта Run = false; -- Прерывает основной цикл WHILE break; else -- УДАЛОСЬ ЗАКРЫТЬ СДЕЛКУ -- Выводит сообщение message('Простой MA-робот: Сделка закрыта по СТОП-ЛОССУ, либо ТЭЙК-ПРОФИТУ'); --Меняет СОСТОЯНИЕ робота на "В ПОИСКЕ ТОЧКИ ВХОДА" ROBOT_STATE = 'В ПОИСКЕ ТОЧКИ ВХОДА'; -- Выводит сообщение message('Простой MA-робот: В ПОИСКЕ ТОЧКИ ВХОДА'); end; else -- Сделку не удалось открыть -- Если первый раз пытался открыть SELL, а операции шорт по данному инструменту запрещены if CurrentDirect == "SELL" and SEC_NO_SHORT then -- Выводит сообщение message('Простой MA-робот: Была первая попытка совершить запрещенную операцию шорт! Больше этого не повторится:)'); --Меняет СОСТОЯНИЕ робота на "В ПОИСКЕ ТОЧКИ ВХОДА" ROBOT_STATE = 'В ПОИСКЕ ТОЧКИ ВХОДА'; -- Выводит сообщение message('Простой MA-робот: В ПОИСКЕ ТОЧКИ ВХОДА'); else -- Выводит сообщение message('Простой MA-робот: После 10-и попыток не удалось открыть сделку!!! Завершение скрипта!!!'); -- Завершает выполнение скрипта Run = false; end; end; else -- СОСТОЯНИЕ робота 'В ПОИСКЕ ТОЧКИ ВХОДА' -- Если на этой свече еще не было открыто позиций if DS:Size() > LastOpenBarIndex then -- Если быстрая пересекла медленную СНИЗУ ВВЕРХ if FastMA(DS:Size()-1) <= SlowMA(DS:Size()-1) and FastMA() > SlowMA() then -- Задает направление НА ПОКУПКУ CurrentDirect = 'BUY'; message('CurrentDirect = "BUY"'); -- Меняет СОСТОЯНИЕ робота на "В ПРОЦЕССЕ СДЕЛКИ" ROBOT_STATE = 'В ПРОЦЕССЕ СДЕЛКИ'; -- Если быстрая пересекла медленную СВЕРХУ ВНИЗ elseif FastMA(DS:Size()-1) >= SlowMA(DS:Size()-1) and FastMA() < SlowMA() then -- Если по данному инструменту не запрещены операции шорт if not SEC_NO_SHORT then -- Задает направление НА ПРОДАЖУ CurrentDirect = 'SELL'; message('CurrentDirect = "SELL"'); -- Меняет СОСТОЯНИЕ робота на "В ПРОЦЕССЕ СДЕЛКИ" ROBOT_STATE = 'В ПРОЦЕССЕ СДЕЛКИ'; end; end; end; end; sleep(10);--Пауза 10 мс, для того, чтобы не перегружать процессор компьютера end; end; -- Функция вызывается терминалом QUIK при получении ответа на транзакцию пользователя function OnTransReply(trans_reply) -- Если поступила информация по текущей транзакции if trans_reply.trans_id == trans_id then -- Передает статус в глобальную переменную trans_Status = trans_reply.status; -- Передает сообщение в глобальную переменную trans_result_msg = trans_reply.result_msg; end; end; -- Функция ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK при остановке скрипта function OnStop() Run = false; end; ----------------------------- -- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ -- ----------------------------- -- Совершает СДЕЛКУ указанного типа (Type) ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот, --- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку function Trade(Type) --Получает ID транзакции trans_id = trans_id + 1; local Price = 0; local Operation = ; --Устанавливает цену и операцию, в зависимости от типа сделки и от класса инструмента if Type == 'BUY' then if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'offer').param_value + 10*SEC_PRICE_STEP;end; -- по цене, завышенной на 10 мин. шагов цены Operation = 'B'; else if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'bid').param_value - 10*SEC_PRICE_STEP;end; -- по цене, заниженной на 10 мин. шагов цены Operation = 'S'; end; -- Заполняет структуру для отправки транзакции local Transaction={ ['TRANS_ID'] = tostring(trans_id), ['ACTION'] = 'NEW_ORDER', ['CLASSCODE'] = CLASS_CODE, ['SECCODE'] = SEC_CODE, ['OPERATION'] = Operation, -- операция ("B" - buy, или "S" - sell) ['TYPE'] = 'M', -- по рынку (MARKET) ['QUANTITY'] = '1', -- количество ['ACCOUNT'] = ACCOUNT, ['PRICE'] = tostring(Price), ['CLIENT_CODE']= 'Простой MA-робот' } -- Отправляет транзакцию sendTransaction(Transaction); -- Ждет, пока получит статус текущей транзакции (переменные "trans_Status" и "trans_result_msg" заполняются в функции OnTransReply()) while Run and trans_Status == nil do sleep(1); end; -- Запоминает значение local Status = trans_Status; -- Очищает глобальную переменную trans_Status = nil; -- Если транзакция не выполнена по какой-то причине if Status ~= 3 then -- Если данный инструмент запрещен для операции шорт if Status == 6 then -- Выводит сообщение message('Простой MA-робот: Данный инструмент запрещен для операции шорт!'); SEC_NO_SHORT = true; else -- Выводит сообщение с ошибкой message('Простой MA-робот: Транзакция не прошла!\nОШИБКА: '..trans_result_msg); end; -- Возвращает FALSE return false; else --Транзакция отправлена local OrderNum = nil; --ЖДЕТ пока ЗАЯВКА на ОТКРЫТИЕ сделки будет ИСПОЛНЕНА полностью --Запоминает время начала в секундах local BeginTime = os.time(); while Run and OrderNum == nil do --Перебирает ТАБЛИЦУ ЗАЯВОК for i=0,getNumberOf('orders')-1 do local order = getItem('orders', i); --Если заявка по отправленной транзакции ИСПОЛНЕНА ПОЛНОСТЬЮ if order.trans_id == trans_id and order.balance == 0 then --Запоминает номер заявки OrderNum = order.order_num; --Прерывает цикл FOR break; end; end; --Если прошло 10 секунд, а заявка не исполнена, значит произошла ошибка if os.time() - BeginTime > 9 then -- Выводит сообщение с ошибкой message('Простой MA-робот: Прошло 10 секунд, а заявка не исполнена, значит произошла ошибка'); -- Возвращает FALSE return false; end; sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера end; --ЖДЕТ пока СДЕЛКА ОТКРЫТИЯ позиции будет СОВЕРШЕНА --Запоминает время начала в секундах BeginTime = os.time(); while Run do --Перебирает ТАБЛИЦУ СДЕЛОК for i=0,getNumberOf('trades')-1 do local trade = getItem('trades', i); --Если сделка по текущей заявке if trade.order_num == OrderNum then --Возвращает фАКТИЧЕСКУЮ ЦЕНУ открытой сделки return trade.price; end; end; --Если прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка if os.time() - BeginTime > 9 then -- Выводит сообщение с ошибкой message('Простой MA-робот: Прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка'); -- Возвращает FALSE return false; end; sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера end; end; end; -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ переданного типа (Type) ["BUY", или "SELL"] function KillPos(Type) -- Дается 10 попыток local Count = 0; -- Счетчик попыток if Type == 'BUY' then -- Пока скрипт не остановлен и позиция не закрыта while Run and not Trade('SELL') do -- Открывает SELL, тем самым закрывая BUY, если Trade('SELL') вернет TRUE, цикл прекратится Count = Count + 1; -- Увеличивает счетчик -- Если за 10 попыток не удалось закрыть позицию if Count == 10 then -- Возвращает NIL return nil; end; sleep(100); -- Пауза 100 мс, чтобы изменилась ситуация на сервере end; else -- Пока скрипт не остановлен и позиция не закрыта while Run and not Trade('BUY') do -- Открывает BUY, тем самым закрывая SELL, если Trade('BUY') вернет TRUE, цикл прекратится Count = Count + 1; -- Увеличивает счетчик -- Если за 10 попыток не удалось закрыть позицию if Count == 10 then -- Возвращает NIL return nil; end; sleep(100); -- Пауза 100 мс, чтобы изменилась ситуация на сервере end; end; -- Возвращает TRUE, если удалось принудительно закрыть позицию return true; end; -- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ (Price) и ТИП (Type) ["BUY", или "SELL"] открытой сделки, --- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, либо TRUE, если сделка закрылась, --- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию function SL_TP(Price, Type) -- ID транзакции trans_id = trans_id + 1;
-- Находит направление для заявки local operation = ""; local price = "0"; -- Цена, по которой выставится заявка при срабатывании Стоп-Лосса (для рыночной заявки по акциям должна быть 0) local stopprice = ""; -- Цена Тэйк-Профита local stopprice2 = ""; -- Цена Стоп-Лосса
local market = "YES"; -- После срабатывания Тэйка, или Стопа, заявка сработает по рыночной цене
-- Если открыт BUY, то направление стоп-лосса и тэйк-профита SELL, иначе направление стоп-лосса и тэйк-профита BUY if Type == 'BUY' then operation = "S"; -- Тэйк-профит и Стоп-лосс на продажу(чтобы закрыть BUY, нужно открыть SELL)
-- Если не акции if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMIN').param_value)); -- Цена выставляемой заявки после страбатывания Стопа минимально возможная, чтобы не проскользнуло market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене end;
stopprice = tostring(Price + TAKE_PROFIT*SEC_PRICE_STEP); -- Уровень цены, когда активируется Тэйк-профит stopprice2 = tostring(Price - STOP_LOSS*SEC_PRICE_STEP); -- Уровень цены, когда активируется Стоп-лосс else -- открыт SELL operation = "B"; -- Тэйк-профит и Стоп-лосс на покупку(чтобы закрыть SELL, нужно открыть BUY)
-- Если не акции
if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then
price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMAX').param_value)); -- Цена выставляемой заявки после страбатывания Стопа максимально возможная, чтобы не проскользнуло market = "NO"; -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене end;
stopprice = tostring(Price - TAKE_PROFIT*SEC_PRICE_STEP); -- Уровень цены, когда активируется Тэйк-профит stopprice2 = tostring(Price + STOP_LOSS*SEC_PRICE_STEP); -- Уровень цены, когда активируется Стоп-лосс end; -- Заполняет структуру для отправки транзакции на Стоп-лосс и Тэйк-профит local Transaction = { ["ACTION"] = "NEW_STOP_ORDER", -- Тип заявки ["TRANS_ID"] = tostring(trans_id), ["CLASSCODE"] = CLASS_CODE, ["SECCODE"] = SEC_CODE, ["ACCOUNT"] = ACCOUNT, ["OPERATION"] = operation, -- Операция ("B" - покупка(BUY), "S" - продажа(SELL)) ["QUANTITY"] = "1", -- Количество в лотах ["PRICE"] = price, -- Цена, по которой выставится заявка при срабатывании Стоп-Лосса (для рыночной заявки по акциям должна быть 0) ["STOPPRICE"] = stopprice, -- Цена Тэйк-Профита ["STOP_ORDER_KIND"] = "TAKE_PROFIT_AND_STOP_LIMIT_ORDER", -- Тип стоп-заявки ["EXPIRY_DATE"] = "TODAY", -- Срок действия стоп-заявки ("GTC" – до отмены,"TODAY" - до окончания текущей торговой сессии, Дата в формате "ГГММДД")
-- "OFFSET" - (ОТСТУП)Если цена достигла Тэйк-профита и идет дальше в прибыль, -- то Тэйк-профит сработает только когда цена вернется минимум на 2 шага цены назад, -- это может потенциально увеличить прибыль
["OFFSET"] = tostring(2*SEC_PRICE_STEP), ["OFFSET_UNITS"] = "PRICE_UNITS", -- Единицы измерения отступа ("PRICE_UNITS" - шаг цены, или "PERCENTS" - проценты)
-- "SPREAD" - Когда сработает Тэйк-профит, выставится заявка по цене хуже текущей на 100 шагов цены, -- которая АВТОМАТИЧЕСКИ УДОВЛЕТВОРИТСЯ ПО ТЕКУЩЕЙ ЛУЧШЕЙ ЦЕНЕ, -- но то, что цена значительно хуже, спасет от проскальзывания, -- иначе, сделка может просто не закрыться (заявка на закрытие будет выставлена, но цена к тому времени ее уже проскочит)
["SPREAD"] = tostring(100*SEC_PRICE_STEP), ["SPREAD_UNITS"] = "PRICE_UNITS", -- Единицы измерения защитного спрэда ("PRICE_UNITS" - шаг цены, или "PERCENTS" - проценты)
-- "MARKET_TAKE_PROFIT" = ("YES", или "NO") должна ли выставится заявка по рыночной цене при срабатывании Тэйк-Профита. -- Для рынка FORTS рыночные заявки, как правило, запрещены, -- для лимитированной заявки на FORTS нужно указывать заведомо худшую цену, чтобы она сработала сразу же, как рыночная
["MARKET_TAKE_PROFIT"] = market, ["STOPPRICE2"] = stopprice2, -- Цена Стоп-Лосса ["IS_ACTIVE_IN_TIME"] = "NO",
-- "MARKET_TAKE_PROFIT" = ("YES", или "NO") должна ли выставится заявка по рыночной цене при срабатывании Стоп-Лосса. -- Для рынка FORTS рыночные заявки, как правило, запрещены, -- для лимитированной заявки на FORTS нужно указывать заведомо худшую цену, чтобы она сработала сразу же, как рыночная
["MARKET_STOP_LIMIT"] = market, ["CLIENT_CODE"] = "Простой MA-робот ТЭЙК-ПРОФИТ и СТОП-ЛОСС" }
-- Отправляет транзакцию на установку ТЭЙК-ПРОФИТ и СТОП-ЛОСС
sendTransaction(Transaction);
-- Ждет, пока не получит статус текущей транзакции (переменные "trans_Status" и "trans_result_msg" заполняются в функции OnTransReply()) while Run and trans_Status == nil do sleep(10); end; -- Запоминает значение local Status = trans_Status; -- Очищает глобальную переменную trans_Status = nil; -- Если транзакция не выполнена по какой-то причине if Status ~= 3 then -- Выводит сообщение с ошибкой message('Простой MA-робот: Установка ТЭЙК-ПРОФИТ и СТОП-ЛОСС не удалась!\nОШИБКА: '..trans_result_msg); -- Возвращает FALSE return false; else -- Выводит сообщение message('Простой MA-робот: ВЫСТАВЛЕНА заявка ТЭЙК-ПРОФИТ и СТОП-ЛОСС: '..trans_id); local OrderNum_CLOSE = nil; -- ЖДЕТ пока СТОП-ЗАЯВКА на СТОП-ЛОСС и ТЭЙК-ПРОФИТ будет ИСПОЛНЕНА полностью while Run and OrderNum_CLOSE == nil do -- Перебирает ТАБЛИЦУ СТОП-ЗАЯВОК for i=0,getNumberOf("stop_orders")-1 do local stop_order = getItem("stop_orders", i); -- Если заявка по текущей транзакции СТОП-ЛОСС и ТЭЙК-ПРОФИТ if stop_order.trans_id == trans_id then -- Если заявка по отправленной СТОП-ЛОСС и ТЭЙК-ПРОФИТ транзакции ИСПОЛНЕНА ПОЛНОСТЬЮ if stop_order.balance == 0 then -- Если по наступлению стоп-цены выставлена заявка if stop_order.linkedorder > 0 then -- Запоминает номер заявки, которая была создана при срабатывании СТОП-ЛОСС, или ТЭЙК-ПРОФИТ OrderNum_CLOSE = stop_order.linkedorder; -- Прерывает цикл FOR break; -- Стоп-заявка сработала, но была отвергнута торговой системой elseif CheckBit(stop_order.flags, 10) == 1 then -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ и выходит из функции return KillPos(Type); end; end; end; end; sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера end; --ЖДЕТ пока СДЕЛКА ЗАКРЫТИЯ позиции будет СОВЕРШЕНА --Запоминает время начала в секундах BeginTime = os.time(); while Run do --Перебирает ТАБЛИЦУ СДЕЛОК for i=0,getNumberOf("trades")-1 do local trade = getItem("trades", i); --Если сделка по текущей заявке на СТОП-ЛОСС и ТЭЙК-ПРОФИТ if trade.order_num == OrderNum_CLOSE then -- Возвращает TRUE return true; end; end; --Если прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка сервера "Обработка кросс-заявок блокирована" if os.time() - BeginTime > 9 then -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ и выходит из функции return KillPos(Type); end; sleep(1); end; end; end; -- Возвращает ЗНАЧЕНИЕ МЕДЛЕННОЙ скользящей по индексу свечи (по умолчанию: последняя) function SlowMA(Index) -- Если индекс свечи не указан, то устанавливает индекс последней свечи if Index == nil then Index = DS:Size(); end; -- Сумма значений SLOW_MA_SOURCE на SLOW_MA_PERIOD свечах local Sum = 0; -- Перебирает последние SLOW_MA_PERIOD свечей for i=Index, Index - (SLOW_MA_PERIOD - 1), -1 do -- Считает сумму, исходя из выбранного источника для медленной скользящей if SLOW_MA_SOURCE == 'O' then Sum = Sum + DS:O(i); elseif SLOW_MA_SOURCE == 'C' then Sum = Sum + DS:C(i); elseif SLOW_MA_SOURCE == 'H' then Sum = Sum + DS:H(i); elseif SLOW_MA_SOURCE == 'L' then Sum = Sum + DS:L(i); else message('Простой MA-робот:ОШИБКА! Не верно указан источник для медленной скользящей!'); -- Останавливает скрипт OnStop(); end; end; -- Возвращает значение return Sum/SLOW_MA_PERIOD; end; -- Возвращает ЗНАЧЕНИЕ БЫСТРОЙ скользящей по индексу свечи (по умолчанию: последняя) function FastMA(Index) -- Если индекс свечи не указан, то устанавливает индекс последней свечи if Index == nil then Index = DS:Size(); end; -- Сумма значений FAST_MA_SOURCE на FAST_MA_PERIOD свечах local Sum = 0; -- Перебирает последние FAST_MA_PERIOD свечей for i=Index, Index - (FAST_MA_PERIOD - 1), -1 do -- Считает сумму, исходя из выбранного источника для быстрой скользящей if FAST_MA_SOURCE == 'O' then Sum = Sum + DS:O(i); elseif FAST_MA_SOURCE == 'C' then Sum = Sum + DS:C(i); elseif FAST_MA_SOURCE == 'H' then Sum = Sum + DS:H(i); elseif FAST_MA_SOURCE == 'L' then Sum = Sum + DS:L(i); else message('Простой MA-робот:ОШИБКА! Не верно указан источник для быстрой скользящей!'); -- Останавливает скрипт OnStop(); end; end; -- Возвращает значение return Sum/FAST_MA_PERIOD; end; -- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil function CheckBit(flags, bit) -- Проверяет, что переданные аргументы являются числами if type(flags) ~= "number" then error("Предупреждение!!! Checkbit: 1-й аргумент не число!"); end; if type(bit) ~= "number" then error("Предупреждение!!! Checkbit: 2-й аргумент не число!"); end; local RevBitsStr = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags) local Fmod = 0; -- Остаток от деления local Go = true; -- Флаг работы цикла while Go do Fmod = math.fmod(flags, 2); -- Остаток от деления flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл end; -- Возвращает значение бита local Result = RevBitsStr :sub(bit+1,bit+1); if Result == "0" then return 0; elseif Result == "1" then return 1; else return nil; end; end;