Торговый робот. Шаг за шагом. Шаг 4. / QUIK Profit
Главная Quikprofit twiiter Quikprofit Rss

Торговый робот. Шаг за шагом. Шаг 4.

Май 3, 2010 | 12 комментариев

Шаг 4.  Переводим алгоритм на язык QPile.

В данном уроке переведем блок-схему первого урока на язык QPile.

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

Ненадолго вернемся к первому уроку и вспомним блок-схему алгоритма для нашего торгового робота, который также описан в первом уроке.

Рис. 4-1 Блок-схема. (Кликабельно)

Блок схема состоит из простых вопросов и однозначных ответов «Да» или «Нет». Для описания этих вопросов и ответов на них будем использовать оператор условия «If».

Синтаксис:

IF условие
последовательность инструкций
ELSE
последовательность инструкций
END IF

Также будут использованы математические, логические и текстовые операции. Подробно о них можно узнать в главе 8 руководства пользователя Quik

Итак, поехали…

Вопрос1. Портфель пустой?

Используем встроенную функцию DEPO_CURRENT_BALANCE

Внимание!!! Использование возможно лишь на спот-рынке. Для срочных рынков применяются другие функции.

DEPO_CURRENT_BALANCE (STRING client_code, STRING firmid, STRING seccode, STRING account)

STRING client_code – код клиента. Для примера возьмем 56786
STRING firmid – фирма. Для примера возьмем MC0567300
STRING seccode – код инструмента. В нашем случае SBER03
STRING account — торговый счет. Для примера возьмем G01-0005D07

Внимание!!! Подробно о данных переменных читайте в статье «Настройка скриптов под свой торговый счет«

Введем переменную ToolQuantity, которой в начале расчета портфеля будет присвоено числовое значение состояния портфеля. Другими словами, какое количество инструмента имеется в наличии на момент расчета. В случае наличия коротких позиций ToolQuantity будет иметь отрицательное значение.

1
ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0

Примечание: «+0» в конце строки переводит переменную ToolQuantity в разряд числовых переменных.

Введем новую переменную в условие.

1
2
3
4
5
If ToolQuantity ==0
	Портфель пустой
else
	Портфель НЕ пустой
end if

Вопрос 2. Можно открыть длинную позицию?

Возвращаясь к первому уроку выясняем условия для входа в длинную позицию. Открывать длинную позицию следует при выполнении трех условий:

  1. ЕМА_1 > ЕМА_2 (Короткая ЕМА выше длинной ЕМА для последней закрытой свечи)
  2. АС_С > 0 (Текущее значение АС выше нулевой черты)
  3. АС_С > АС_С_1 (Текущее значение АС больше предыдущего значения)

Для того, чтобы поставить все 3 условия одновременно используем логическую операцию «И» («AND»). Необходимые для условия переменные были заданы в третьем уроке.

Условие выглядит следующим образом:

1
2
3
If  (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1)
	Выполнены все условия, выставляем заявку на покупку.
End if

Примечание. Выставление заявок будет рассмотрено в следующих уроках.

Теперь переходим к блоку «Портфель НЕ пустой»

Вопрос 4. Можно закрыть длинную позицию?

По условиям технического задания основание для выхода из длинной позиции служит переход индикатора АС в отрицательную зону, т.е. AC < 0. Так и запишем.

1
2
3
 If  (ToolQuantity>0) and (АС_С < 0)
	Закрываем позицию, выставляя заявку на продажу.
End if

Вопрос 5. Можно закрыть короткую позицию?

Аналогично вопросу 4 получаем:

1
2
3
If  (ToolQuantity<0) and (АС_С > 0)
	Закрываем позицию, выставляя заявку на покупку.
End if

Итак, мы записали все вопросы блок-схемы на языке QPile. Пришло время сложить все имеющиеся кубики торгового робота воедино.

Кубик с необходимыми переменными:

1
ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0

Кубик с вопросами:

1
2
3
4
5
6
7
8
9
10
11
If ToolQuantity ==0
	If  (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1)
		Заявка на покупку
	End if
	If  (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) 		Заявка на продажу 	End if Else 	If  (ToolQuantity>0) and (АС_С < 0)
		Заявка на продажу
	End if
	If  (ToolQuantity<0) and (АС_С > 0)
		Заявка на покупку
	End if
End if

Общий текст программы будет иметь вид:

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
PORTFOLIO_EX EMAvsAC;
DESCRIPTION Робот ЕМА и АС;
CLIENTS_LIST ALL_CLIENTS;
FIRMS_LIST ALL_FIRMS;
INCLUDE fGetMA.qpl, fGetAC.qpl;
 
PROGRAM
'Наш первый Портфель на основе ЕМА и АС
'Версия 0.1
DELETE_ALL_ITEMS () 'Благодаря этой функции из таблицы будут удалены старые значения.
'Короткая ЕМА (ЕМА_1) для последней закрытой свечи
dataMA9 = fGetMA("SBEREMA9", 2,  15)
EMA_1 = get_value (dataMA9,"MA_MAIN")+0
'Длинная ЕМА (ЕМА_2) для последней закрытой свечи
dataMA25 = fGetMA("SBEREMA25", 2,  15)
EMA_2 = get_value (dataMA25,"MA_MAIN")+0
'Текущее значение AC (АС_С) в незакрытой свече
dataAC1 = fGetAC("SBERAC", 1,  15)
AC_C = get_value (dataAC1,"AC_MAIN")+0
'Значение АС в последней закрытой свечи (АС_С_1)
dataAC2 = fGetAC("SBERAC", 2,  15)
AC_C_1 = get_value (dataAC2,"AC_MAIN")+0
ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0
If ToolQuantity == 0
	If  (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1)
		Заявка на покупку
	End if
	If  (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) 		 Заявка на продажу 	End if Else 	If (ToolQuantity>0) and (АС_С < 0)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
		 Заявка на продажу
	End if
	If (ToolQuantity<0) and (АС_С > 0)
		Заявка на покупку
	End if
End if
 
Massiv = CREATE_MAP() 'Создали массив с названием Massiv
Last_price = GET_VALUE(GET_PARAM_EX("EQBR","SBER03","last"),"param_value") 'Достаем из таблицы текущих параметров цену последней сделки по инструменту
Massiv = SET_VALUE(Massiv,"SecCode","СБЕРБАНК") 'Записали в массив наименование инструмента
Massiv = SET_VALUE(Massiv,"LastPrice", Last_price) 'Записали в массив цену последней сделки по инструменту
Massiv = SET_VALUE(Massiv,"EMA_1", EMA_1)
Massiv = SET_VALUE(Massiv,"EMA_2", EMA_2)
Massiv = SET_VALUE(Massiv,"AC_C", AC_C)
Massiv = SET_VALUE(Massiv,"AC_C_1", AC_C_1)
ADD_ITEM(0, Massiv)
END_PROGRAM
 
PARAMETER SecCode;
PARAMETER_TITLE Инструмент;
PARAMETER_DESCRIPTION Наименование инструмента;
PARAMETER_TYPE String(10);
END
PARAMETER LastPrice;
PARAMETER_TITLE Цена;
PARAMETER_DESCRIPTION Цена последней сделки по инструменту;
PARAMETER_TYPE Numeric(10,2);
END
PARAMETER EMA_1;
PARAMETER_TITLE ЕМА_1;
PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 9;
PARAMETER_TYPE Numeric(10,6);
END
PARAMETER EMA_2;
PARAMETER_TITLE ЕМА_2;
PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 25;
PARAMETER_TYPE Numeric(10,6);
END
PARAMETER AC_C;
PARAMETER_TITLE АС незакрытой свечи;
PARAMETER_DESCRIPTION АС незакрытой свечи;
PARAMETER_TYPE Numeric(10,6);
END
PARAMETER AC_C_1;
PARAMETER_TITLE АС закрытой свечи;
PARAMETER_DESCRIPTION АС закрытой свечи;
PARAMETER_TYPE Numeric(10,6);
END
 
END_PORTFOLIO_EX

Однако в таком виде мы не можем загрузить наш портфель в Quik. Дело в строках «Заявка на покупку» и «Заявка на продажу».

Но нет худа без добра, не так ли?

Вместо мешающих загрузки портфеля строк поставим команды, которые будут фиксировать наступление того или иного события.

Внимание!!! Подробно о методе можно прочитать в статье «Что он там делает?» Следим за работой робота.

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

Первым делом прикрепим необходимую внешнюю функцию fDebugLog.qpl (Как это сделать читайте в 3м уроке)

Далее определим что же именно мы будем фиксировать в журнале.

1
2
3
4
5
6
7
8
9
10
11
If ToolQuantity == 0
	If  (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1)
		fDebugLog("Портфель пустой. Выполнено условие для ЛОНГа. Ставим заявку на покупку")
	End if
	If  (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) 		fDebugLog("Портфель пустой. Выполнено условие для ШОРТа. Ставим заявку на продажу") 	End if Else 	If (ToolQuantity>0) and (АС_С < 0)
		fDebugLog("Открыта позиция ЛОНГ. Выполнено условие для закрытия позиции. Ставим заявку на продажу")
	End if
	If (ToolQuantity<0) and (АС_С > 0)
		fDebugLog("Открыта позиция ШОРТ. Выполнено условие для закрытия позиции. Ставим заявку на покупку")
	End if
End if

Делаем правки в тексте портфеля и получаем:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
PORTFOLIO_EX EMAvsAC;
DESCRIPTION Робот ЕМА и АС;
CLIENTS_LIST ALL_CLIENTS;
FIRMS_LIST ALL_FIRMS;
INCLUDE fGetMA.qpl, fGetAC.qpl, fDebugLog.qpl;
 
PROGRAM
'Наш первый Портфель на основе ЕМА и АС
'Версия 0.1
DELETE_ALL_ITEMS () 'Благодаря этой функции из таблицы будут удалены старые значения.
'Короткая ЕМА (ЕМА_1) для последней закрытой свечи
dataMA9 = fGetMA("SBEREMA9", 2,  15)
EMA_1 = get_value (dataMA9,"MA_MAIN")+0
'Длинная ЕМА (ЕМА_2) для последней закрытой свечи
dataMA25 = fGetMA("SBEREMA25", 2,  15)
EMA_2 = get_value (dataMA25,"MA_MAIN")+0
'Текущее значение AC (АС_С) в незакрытой свече
dataAC1 = fGetAC("SBERAC", 1,  15)
AC_C = get_value (dataAC1,"AC_MAIN")+0
'Значение АС в последней закрытой свечи (АС_С_1)
dataAC2 = fGetAC("SBERAC", 2,  15)
AC_C_1 = get_value (dataAC2,"AC_MAIN")+0
ToolQuantity = DEPO_CURRENT_BALANCE("56786", "MC0567300", "SBER03", "Y62-000098B01") +0
If ToolQuantity == 0
	If  (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1)
		fDebugLog("Портфель пустой. Выполнено условие для ЛОНГа. Ставим заявку на покупку")
	End if
	If  (ЕМА_1 < ЕМА_2) and (АС_С < 0) and (АС_С < АС_С_1) 		fDebugLog("Портфель пустой. Выполнено условие для ШОРТа. Ставим заявку на продажу") 	End if Else 	If (ToolQuantity>0) and (АС_С < 0)
		fDebugLog("Открыта позиция ЛОНГ. Выполнено условие для закрытия позиции. Ставим заявку на продажу")
	End if
	If (ToolQuantity<0) and (АС_С > 0)
		fDebugLog("Открыта позиция ШОРТ. Выполнено условие для закрытия позиции. Ставим заявку на покупку")
	End if
End if
 
Massiv = CREATE_MAP() 'Создали массив с названием Massiv
Last_price = GET_VALUE(GET_PARAM_EX("EQBR","SBER03","last"),"param_value") 'Достаем из таблицы текущих параметров цену последней сделки по инструменту
Massiv = SET_VALUE(Massiv,"SecCode","СБЕРБАНК") 'Записали в массив наименование инструмента
Massiv = SET_VALUE(Massiv,"LastPrice", Last_price) 'Записали в массив цену последней сделки по инструменту
Massiv = SET_VALUE(Massiv,"EMA_1", EMA_1)
Massiv = SET_VALUE(Massiv,"EMA_2", EMA_2)
Massiv = SET_VALUE(Massiv,"AC_C", AC_C)
Massiv = SET_VALUE(Massiv,"AC_C_1", AC_C_1)
ADD_ITEM(0, Massiv)
END_PROGRAM
 
PARAMETER SecCode;
PARAMETER_TITLE Инструмент;
PARAMETER_DESCRIPTION Наименование инструмента;
PARAMETER_TYPE String(10);
END
PARAMETER LastPrice;
PARAMETER_TITLE Цена;
PARAMETER_DESCRIPTION Цена последней сделки по инструменту;
PARAMETER_TYPE Numeric(10,2);
END
PARAMETER EMA_1;
PARAMETER_TITLE ЕМА_1;
PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 9;
PARAMETER_TYPE Numeric(10,6);
END
PARAMETER EMA_2;
PARAMETER_TITLE ЕМА_2;
PARAMETER_DESCRIPTION MovingAverage с параметрами Exponential, 25;
PARAMETER_TYPE Numeric(10,6);
END
PARAMETER AC_C;
PARAMETER_TITLE АС незакрытой свечи;
PARAMETER_DESCRIPTION АС незакрытой свечи;
PARAMETER_TYPE Numeric(10,6);
END
PARAMETER AC_C_1;
PARAMETER_TITLE АС закрытой свечи;
PARAMETER_DESCRIPTION АС закрытой свечи;
PARAMETER_TYPE Numeric(10,6);
END
 
END_PORTFOLIO_EX

Таким образом, в любой момент времени мы можем узнать из журнала, что нам предлагает делать робот в тот или иной момент времени.

P.S. Вы можете скачать представленный код одним файлом, а также вышеуказанную функцию.

Скачать Lesson 4

Понравилось? Следите за обновлениями по RSS! Также можете следить за обновлениями в Twitter.
          0 проголосовавших

Комментарии

12 ответов to “Торговый робот. Шаг за шагом. Шаг 4.”

  1. Денис
    Июнь 26th, 2010 @ 11:00

    У меня почемуто выдает ошибку на строке 25.
    If (ЕМА_1 > ЕМА_2) and (АС_С > 0) and (АС_С > АС_С_1)
    Найти ошибку не смог. Помогите разобраться что не так…

  2. Sergey
    Июнь 27th, 2010 @ 16:41

    Можете подробнее описать ошибку?

  3. Денис
    Июнь 28th, 2010 @ 20:15
  4. Константин
    Июнь 30th, 2010 @ 18:34

    У меня тоже выдаёт ошибку в строке условий на покупку

  5. Денис
    Июнь 30th, 2010 @ 20:27

    А при загрузке в Квик не выдает?

  6. Константин
    Июль 1st, 2010 @ 12:06

    Аналогично, при загрузке в Квик не выдает

  7. Ю.Р.
    Июль 8th, 2010 @ 21:38

    Ошибка исправлена. Файл перезалит.
    Ошибка «Unknown lexema» означает, что в строке имеется неизвестный знак. QPile очень чувствителен к символам, шрифтам.

  8. konstnk
    Июль 9th, 2010 @ 09:16

    Сообщите пожалуйста в чём была ошибка. После устранения вами этой ошибки, Квик указывает на аналогичную ошибку в строке If (ToolQuantity 0)

  9. konstnk
    Июль 9th, 2010 @ 09:21

    Сообщите пожалуйста в чём была ошибка. После устранения вами этой ошибки, Квик указывает на аналогичную ошибку в строке If (ToolQuantity 0)

  10. konstnk
    Июль 9th, 2010 @ 09:24

    Строка почемуто правильно не копируется.

  11. Денис
    Июль 13th, 2010 @ 10:53

    «Ошибка исправлена. Файл перезалит.»
    Что-то я не заметил разницы…
    Квик все так же ругается…

  12. quazar
    Январь 12th, 2011 @ 13:57

    25 и 36 строки надо вручную переписать, там где-то буква А или С не на латинской раскладке набрана, а на кририллической

Оставить комментарий





Поля помеченные (*) обязательны к заполнению

Страница 1 из 11
  • Меню

  • Облако тегов

  • Рубрики

  • Для пользователя