Функция выставления заявок

При разработке нескольких торговых роботов часто приходится сталкиваться с использованием одних и тех же функций, которые приходится модернизировать для различных задач. В частности, функцию выставления заявок. В одной системе необходимо выставлять лимитированные заявки на покупку акций, в другой - хватать по рыночной цене фьючерсы. Функции выставления заявок во всех случаях похожи, но не одинаковы. Поэтому решил я заняться унификацией.

Варианты использования:

' Лимитированная заявка на покупку акций Газпрома:
send_order ("B","143.50","L","GAZP","EQNE","245","1")
' Заявка на продажу акций Газпрома по рыночной цене:
send_order ("S","0","M","GAZP","EQNE","233","2")
' Лимитированная заявка на покупку фьючерсов Газпрома:
send_order ("B","14350","L","GZU9","SPBFUT","10","3")
' Заявка на продажу фьючерсов Газпрома по рыночной цене:
send_order ("S","0","M","GZU9","SPBFUT","9","4")

Собственно, сама функция.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
FUNC send_order (Operation,Price,Type,SecCode,ClassCode,Quantity,TransID)
	trans_params = ""
	trans_params = set_value (trans_params, "TRANS_ID",    TransID)
	trans_params = set_value (trans_params, "ACTION",     "NEW_ORDER")
	trans_params = set_value (trans_params, "CLASSCODE",   ClassCode)
	trans_params = set_value (trans_params, "SECCODE",     SecCode)
	trans_params = set_value (trans_params, "OPERATION",   Operation)
	trans_params = set_value (trans_params, "QUANTITY",    Quantity)
	trans_params = set_value (trans_params, "TYPE",        Type)
	trans_params = set_value (trans_params, "CLIENT_CODE", ClientCode)
    Account = AccMicex
	IF ClassCode == "SPBFUT"
        Account = AccRTS
        IF Price == "0" ' 
			IF Operation = "B"
				Price = 0 + GET_PARAM(ClassCode, SecCode, "offer") _
				+ 5*CEIL(Slip*GET_PARAM(ClassCode, SecCode, "offer"))
			END IF
			IF Operation = "S"
				Price = 0 + GET_PARAM(ClassCode, SecCode, "bid") - _
				5*CEIL(Slip*GET_PARAM(ClassCode, SecCode, "bid"))
			END IF
		END IF
	END IF
    trans_params = set_value (trans_params, "ACCOUNT",     Account)
	trans_params = set_value (trans_params, "PRICE",       Price)
	trans_result = SEND_TRANSACTION (300, trans_params)
	FOR while FROM 0 TO 1000
		'while = 0 
		IF GET_VALUE (trans_result, "RESULT_EX") == "3" 
			OrderNumber = GET_VALUE(trans_result, "ORDER_NUMBER") 
			RESULT = 1
			RETURN 
		END IF
	END FOR
END FUNC

Заранее определяемые переменные:

AccMicex   = "Ф00-00000000"
AccRTS     = "SPBFUT00000"
ClientCode = "0000000/0000000"
Slip = 0.001 ' Величина в долях для возможного отклонения при покупке фьючерсов по рыночной цене

Некоторые пояснения:
Operation - "B" или "S" - Бай или Селл.
Price - цена. Если "0", то рыночная.
Type - "M" или "L" - Рыночная или Лимитированная.
SecCode - инструмент.
ClassCode - код класса. "SPBFUT" для фьючерсов.
Quantity - количество лотов.
TransID - ID транзакции.

Всё остальное в файле: функция выставления заявок.

Приветствуются дополнения и пожелания.


29 комментариев для “Функция выставления заявок”

  • 21 Июль, 2009, 1:04

    Если для выставления всех заявок в роботе будет использоваться одна универсальная функция, то, по-моему, логичней было бы TransID не выносит в параметры, а рассчитывать в самой функции.
    Объявить переменную глобальной:
    NEW_GLOBAL(TransID, N)
    И в любой функции выставления заявок, например, первой строкой писать:
    TransID = TransID + 1
    Этим будет обеспечиваться уникальность кода каждой транзакции.
    Спасибо.

    Блог весьма интересный.

  • 20 Август, 2009, 10:19

    Это правильно. Но иногда необходимо помнить все позиции по номерам.

  • rusl
    20 Август, 2009, 16:22

    )) где у вас контакты, куда обратиться ? вопрос простой - пишите ли вы роботов ( несложных) по заказу ?

  • Иван
    20 Август, 2009, 19:50

    Контакты я убрал, т.к. до октября (как минимум) заказы не принимаю. Ну а вообще да, пишу.

  • Алексей
    12 Сентябрь, 2009, 17:52

    Иван, хотел обратиться с вопросом написания робота. стратегия простая, без наворочек. просьба связяться со мной как у вас появится время flatchers at gmail . com

  • dachnik
    12 Октябрь, 2009, 10:39

    В примере функции выставления заявки вероятно ошибка
    IF Operation = "B"
    Должно быть написано как
    IF Operation == "B"
    Тоже самое и для Sell

  • Иван
    12 Октябрь, 2009, 13:52

    Замечание верное, но ошибки нет, код рабочий.

  • Сергей из Чебоксар
    12 Октябрь, 2009, 15:01

    А разве есть разница между = и ==? В обоих случаях равно.

  • dachnik
    15 Октябрь, 2009, 13:28

    Почему-то IF Price == "0" возвращает ошибку что-то типа не соответсвия типов, заменил на IF Price <1
    Но столкнулся с др. проблемой
    Price = 0 + GET_PARAM(ClassCode, SecCode, "offer") на одном компе работает и возвращает цену, на другом компе не выполняется, соотвественно заявка не проходит из-за цены сделки вне лимита.

  • Buba
    16 Октябрь, 2009, 15:54

    Нужно написать механические торговую систему для QUIK на QPILE, ТЗ есть. Оставьте контакт.

  • dachnik
    16 Октябрь, 2009, 18:04

    По поводу предедущих постов, нашел ошибку
    send_order ("S",0,"M","GZU9","SPBFUT","9","4"), при отправке заявки ноль не в кавычках, хотя под XP работало, под Вистой нет. А вот почему скрипт не выполняется пока цена бумаги не меняется, вопрос.

  • Владимир
    18 Октябрь, 2009, 18:55

    Здравствуйте,Иван.

    Интересует индивидуальное написание скрипта.

  • Юра
    20 Октябрь, 2009, 10:36

    Спасибо за сайт! очень полезен!
    Участок кода вызвал вопрос

    trans_result = SEND_TRANSACTION (300, trans_params)
    FOR while FROM 0 TO 1000
    IF GET_VALUE (trans_result, "RESULT_EX") == "3"

    Посылается заявка один раз,
    ее результат возвращается один раз,
    а сверяется результат на равенство "3" тысячу раз?

    Я только начал осваивать язык, но мне кажется тут ошибка.
    Корректный вариант, имхо
    FOR while FROM 0 TO 1000
    trans_result = SEND_TRANSACTION (300, trans_params)
    IF GET_VALUE (trans_result, "RESULT_EX") == "3"

  • Иван
    20 Октябрь, 2009, 12:04

    Вы хотите тысячу раз послать транзакцию и вызвать гнев брокера?
    Тут логика такая. Отправляем транзакцию и ждем результата исполнения. Если всё хорошо, то мы быстро его узнаем. Если нет, то немного подождем и выйдем из функции. Бывает, что в этом месте идет зависание терминала, если использовать бесконечный цикл.
    Так что выбран такой вариант, он рабочий.

  • Юра
    20 Октябрь, 2009, 12:11

    Понял вас, не разобрался с параметром SEND_TRANSACTION (300, trans_params)
    Спасибо за ответ

  • dachnik
    22 Октябрь, 2009, 8:15

    1) Проблема осталась. Почему-то IF Price == "0" возвращает ошибку что-то типа не соответсвия типов, заменил на IF Price <1, но тоже бывают глючит. Причем три дня нормально работает на четвертый может перестать.
    2) Price = 0 + GET_PARAM(ClassCode, SecCode, "offer") пришлось пернести в тело программы, когда была в функции почему не всегда работала.
    3) Слышал что можно в Quik как-то заливать историю которовок и отлаживать прогу не во время сессии, а на прокрутке истории котировок. Было бы очень полезно, а то у меня от не сработанных стопов уже депо начало уменьшаться.

  • 22 Октябрь, 2009, 10:35

    На официальном форуме читал, что можно запускать Quik в оффлайне, но чтобы что-то отлаживать - впервые слышу. Полезно было бы, это факт.

  • Александр
    8 Ноябрь, 2009, 21:08

    Как соотносится число 300 с реальным временем?
    (Речь о SEND_TRANSACTION (300, trans_params)) Это много или мало?

  • Иван
    8 Ноябрь, 2009, 22:02

    Это время ожидания ответа торговой системы в секундах (минимум 5).
    300 секунд - это много. Зато с запасом.

  • Сергей из Чебоксар
    8 Ноябрь, 2009, 22:08

    Что подразумевается под ожиданием? ЕСли заявка не исполняется в течении 300 секунд, она отменяется?

  • Александр
    9 Ноябрь, 2009, 0:25

    А если объемов не хватит на рынке (в стакане) для заявки по рыночной цене? Тогда как?

  • 9 Ноябрь, 2009, 17:45

    Раздел 8.21.1 ничего не сообщает о том, что будет по истечении указанного времени. Да и мне не доводилось встречаться.

    Если не хватит объемов, то заявка будет частично исполненной. Либо даже не начнет исполнятся, такое вероятнее.

  • Дмитрий
    10 Ноябрь, 2009, 8:25

    Добрый день! Если далее нужно соответственно поставить стоп-со связанной возможно ли это?

  • d4802
    10 Ноябрь, 2009, 22:14

    Всем доброго дня! У меня вопрос: при совершении сделки не роботом, а "вручную" по определённой цене (не по рынку) каким образом "взять" цену, направление, объём этой сделки из QUIKа, а именно из таблицы исполненных заявок - ведь их там накапливается много. И последняя по счёту сделка тоже не факт что нужная нам, если в дальнейшем на базе открытой сделки будет выставлена к примеру сделка по продаже?

  • Иван
    11 Ноябрь, 2009, 0:06

    У каждой заявки есть свой уникальный номер. Этого достаточно для определения необходимых параметров.

  • Денис
    2 Декабрь, 2009, 13:03

    спасибо за интересный сайт. интересует готовый проверенный робот. не получается постоянно торчать у компа, нужна помощь машины. есть ли предложения?

  • Аhiles84
    11 Октябрь, 2010, 11:38

    Иван ОГРОМНОЕ Вам СПАСИБО !

    ЭТО САМЫЙ ПОЛЕЗНЫЙ САЙТ ПО РОБОТАМ

  • Дмитрий
    21 Ноябрь, 2010, 0:39

    Здравствуйте!
    Во-первых, спасибо Вам огромное за этот замечательный сайт. Единственное место, где я нашел замечательные, работающие уроки!

    А во-вторых, у меня к Вам вопрос - как нужно изменить приведенный выше код, чтобы выставить тэйк-профит? =)

  • Павел
    13 Январь, 2011, 15:56

    Транс ИД можно один и тот-же слать, я его вообще для идентификации заявок конкретного робота использую. Чтобы можно было много одинаковых роботов на одном счету пускать.
    Только вечерний ТрансИД пропадает утром, так что на ночь такие заявки оставлять нельзя, утром не найдёшь. И ещё в этой "унифункции" очень слаба обработка внештатных ситуаций (зависание сервера, отвержение заявки, недостаток средств и т.п.)