Итак, давайте пофантазируем и придумаем свой собственный робот, который вполне может быть использован для торговли в ряде случаев.
Начнем с идеи, т.к. с идеи начинается все великое.
Итак, нам хотелось бы, чтобы наша программа позволяла:
— работать только внутри дня;
— зарабатывать устанавливаемый нами уровень дохода в день;
— иметь встроенный ограничитель убытков;
— работать в двух направлениях и в лонг и в шорт;
— иметь разные следящие стратегии.
— отображать в отдельном окне все текущие параметры работы алгоритма с максимальной подробностью. Это позволит Вам быстрее понять, что вообще происходит, а также вводить коррективы в работу роботу.
Так, вроде неплохо. Это идея так идея, но можно ли ее реализовать? На самом деле идеальный робот, конечно, никогда не получается. Но в том и прелесть програамирования, что по ходу тестирования Вашей разработки Вы будете путем отсечения «багов» оттачивать ее до совершенства. Мы не претендуем на то, чтобы дать такую идеальную программу. Тем не менее, мы дадим очень интересный код, обладающий достаточной сложностью с влечением почти всех возможностей языка ATF для достижения поставленной задачи.
Также мы добавим в наш алгоритм одну очень востребованную функцию. Дело в том, что робот может строчить сделки с немыслимой скоростью. А чем больше сделок, тем выше комиссия. При работе с небольшими суммами, правило комиссии в 0,0375%, но не менее 41 рубля за сделку может нас бысто разорить. При закрытии сделок по рынку часто получается так, что вместо одной сделки мы получаем иногда до 10 сделок, например, надо продать 100 лотов, в стакане сидят мелкие заявки на 3, 5, 10 лотов. Т.е. чтобы набрать 100 лотов надо собрать всех, кто сидит в стакане до крупняка, который наконец-таки проглотит наш остаток одной сделкой. Ну так вот. Мы добавим функцию, которая будет искать позицию в стакане где сидит крупняк и будем сразу закрывать сделку за раз! Блестящая идея, не правда ли? Это резко добавляет ценности нашему роботу.
Обратим внимание, что данный робот рабочий (пр проверке скрипта выдаст «Ок»), но использовать его в целях зарабатываняи денег Вы должны на свой страх и риск, поскольку автор не может гарантировать отсутствие убытков при использовании данного робота. Рекомендуем сначала ознакомиться с его работой на небольших суммах и выявить особенности его работы. В переменных я задал ограничение используем суммы не более 1000 рублей. Вы, конечно же, можете задать нужное значение.
Листинг 2. Робот «MoneyTrain release 1» (авторская редакция)
//Trade Robot MoneyTrain rel.1
#samewindow
#line 0 nodraw
//#line 0 dashed #C0C0C0
//#line 1 dashed #AAC0C0
//Перечень переменных для управления стратегией Денежный поезд
//Шаг риска в %
static procent_profit = 0.5;
//Длительность реакции на изменение цены
extern time_shift_second = 5;
//Включить отслеживание изменения цены 1 выключить 0
extern price_tracking = 1;
//Лимит суммы, участвующей в торговле в рублях
extern summ_limit = 1000;
//задержка для определения направления движения рынка при старте
extern timer2_shift_second = 3;
//желаемая прибыль в % в течение дня (без учета налогов и оплаты услуг брокера)
static wish_profit_in_procent = 1.5;
//Допустимое число сделок, после достижения программа останавливается или раньше если желаемая прибыль получена
extern orders_count_limit = 6;
//Число циклов для осуществления наблюдения за уровнем убытков. Для отключения равно 0.
extern loss_cycle = 0;
//разница при сравнении роста убытка
extern loss_procent = 0.25;
//стратегия отслеживания шумов рынка с адаптацией под них
//использовать стратегию отслеживания
extern use_tracking_strategy = 1;
//интервал отсдеживания в часах
static tracking_interval_in_h = 0.5;
//допустимое число сделок за интервал
static orders_count_for_tracking = 3;
//коэффициент реакции на шумы. Шаг риска умножается/делится на данный коэфф. в течение текущего интервала отслеживания
static noise_koeff = 1.33;
//Цена за 1 сделку в рублях
static price_of_trade = 41;
//Нам также понадобяться переменные для обращения к файлам
var file;
var file1;
var file2;
//1 — обычная заявка, 0 — стоп заявка
var flow_order;
var stop_id;
static flow_price;
static timer1 = 0;
static timer2 = 0;
var timer2_price;
var book;
static start_balance = 0;
static stop_algoritm;
static orders_count = 0;
static price_at_start;
//пременные управления циклами
static summ_timer = 0;
static orders_for_interval = 0;
static flow_profit;
static cycle_i = 0;
static cycle_start_value;
static cycle_end_value;
static cycle_direction = 0;
static step_book;
static n_lots;
//функция для записи события в файл.
function message_write(var mess)
{
if (file2.isopen())
{
file2.writeLn(mess);
}
}
//Действия при старте ATF скрипта. Ставится перед всеми функциями. Функция message_write не мешает этому правилу.
function init()
{
//Выполняем синхронизацию времени с сервером биржи.
var exec_time = getSystemTime();
var dt = getFormattedDateTime(exec_time);
var nl;
//Создаем новый файл для хранения генерируемых программой сообщений
file = new_object(«file»);
file.waopen(«mtrain_log.txt»);
file.writeLn(dt);
file2 = new_object(«file»);
file2.waopen(«mtrain_log_all.txt»);
//Выдаем сообщение в окно сообщений и записываем его также в файл записей сообщений
signal::outputMultiple(«Init start»);
message_write(«Init start»);
//Остановка второго таймера если он был активирован
timer2_price = close;
signal::outputMultiple(«Close is » + close+ «!»);
message_write(«Close is » + close+ «!»);
signal::outputMultiple(«Init end»);
message_write(«Init end»);
//Создание второго таймера
timer2 = setTimer(«onTimer2», timer2_shift_second * 1000, TIMER_PERIODICALLY);
//Создаем объект для обращения к стакану
book = new_object(«book»);
book.subscribe();
stop_algoritm = false;
//учитываем в прибыле налоговую ставку
wish_profit_in_procent = wish_profit_in_procent * 1.13;
step_book = 0;
}
//Созадем функцию для запроса количества акций в лоте инструмента, запроса текущего баланса на счете. Задаем запас 5% чтобы не превысить баланс счета
function get_number_of_lots(var act_price_lot)
{
var rl;
var sl;
var res;
var res1;
rl = getLotSize();
res1 = getMoneyBalance();
signal::outputMultiple(«Balance: » + res1 + » rub»);
message_write(«Balance: » + res1 + » rub»);
sl = summ_limit * 0.95;
if (res1 < summ_limit)
{
sl = res1;
}
res = int(sl/rl/act_price_lot);
signal::outputMultiple(«Number of lots » + res + «!»);
message_write(«Number of lots » + res + «!»);
return res;
}
//Функция для обработки и записи в файл данных о совершенных сделках
function saveTrade(var order)
{
//Синхронизируем системное время со временем сервера
setSystemTime(getServerTime());
var exec_time = getSystemTime();
var dt = getFormattedDateTime(exec_time);
var sec_array = new_object(«array»);
var size_a;
var rl;
file.write(«Order: «);
file.write(» » + order[«orderno»] + «; «);
if (order[«operation»] == OP_BUY) {
file.write(«BUY «);
}
else {
file.write(«SELL «);
}
file.write(dt + «; «);
file.write(getSecName() + «; «);
file.write(order[«quantity»]);
file.write(» lots at price «);
sec_array = getAllTradeIDsBySec();
size_a = sec_array.size();
size_a = getTrade(sec_array[size_a-1]);
if (order[«price»] == -1)
{
file.writeLn(size_a[«price»]);
}
else
{
file.writeLn(order[«price»]);
}
}
//запись идентификатора транзакции производимой Timer2 в файл trnid.txt
function trnid_write(var tr_nid)
{
file1 = new_object(«file»);
file1.wopen(«trnid.txt»);
file1.seek(0);
file1.writeLn(tr_nid);
file1.close();
signal::outputMultiple(«TRNID was wrote»);
message_write(«TRNID was wrote»);
}
//чтение идентификатора транзакции производимой Timer2 из файла trnid.txt
function trnid_read()
{
var res;
file1 = new_object(«file»);
file1.ropen(«trnid.txt»);
if (file1.isopen()) {
res = file1.readLn();
file1.close();
signal::outputMultiple(«TRNID » + res);
message_write(«TRNID » + res);
return res;
}
}
//Функция выставления заявок
function set_order(var order)
{
var stop = new_object(«hash»);
var act_price;
var rl = 0;
var order_quantity = 0;
var tr;
var sec_array = new_object(«array»);
var size_a;
signal::outputMultiple(«Set_Order is started»);
message_write(«Set_Order is started»);
if (isTradingAllowed()) {
signal::outputMultiple(«Order Op is » + order[«orderno»]);
message_write(«Order Op is » + order[«orderno»]);
sec_array = getAllTradeIDsBySec();
size_a = sec_array.size();
size_a = getTrade(sec_array[size_a-1]);
// Заявка на продажу
if (order[«operation»] == OP_SELL) {
stop[«operation»] = OP_BUY;
if (order[«price»] == -1) {
act_price = size_a[«price»]*(1 + procent_profit/100);
}
else
{
act_price = order[«price»]*(1 + procent_profit/100);
}
signal::outputMultiple(«Order Op is » + «SELL»);
message_write(«Order Op is » + «SELL»);
}
//Заявка на покупку
if (order[«operation»] == OP_BUY) {
stop[«operation»] = OP_SELL;
if (order[«price»] == -1) {
act_price = size_a[«price»]/(1 + procent_profit/100);
}
else
{
act_price = order[«price»]/(1 + procent_profit/100);
}
signal::outputMultiple(«Order Op is » + «BUY»);
message_write(«Order Op is » + «BUY»);
}
order_quantity = n_lots;
signal::outputMultiple(«Price is » + act_price + «!»);
message_write(«Price is » + act_price + «!»);
// Часть Stop Loss
stop[«sl_activationprice»] = act_price;
stop[«sl_quantity»] = order_quantity*2;
stop[«sl_usecredit»] = true;
// Выставление стоп-заявки на рынок
//stop_id = trade_action::transactMultiple(stop);
//Обработка таймера алгоритма слежения за текущей ценой
if (price_tracking)
{
signal::outputMultiple(«Timer1 was checked «);
message_write(«Timer1 was checked «);
if (timer1)
{
delTimer(timer1);
timer1 = 0;
signal::outputMultiple(«Timer1 was killed «);
message_write(«Timer1 was killed «);
}
timer1 = setTimer(«onTimer1», time_shift_second * 1000, TIMER_PERIODICALLY);
}
}
signal::outputMultiple(«Set_Order is end»);
message_write(«Set_Order is end»);
}
//Функция обработки события выставения заявки
function onOrder(var id)
{
signal::outputMultiple(«OnOrder is activated»);
message_write(«OnOrder is activated»);
signal::outputMultiple(«OnOrder ID is » + id);
message_write(«OnOrder ID is » + id);
var order = getOrder(id);
signal::outputMultiple(«Order Number is » + order[«orderno»]);
message_write(«Order Number is » + order[«orderno»]);
signal::outputMultiple(«Order status is » + order[«status»]);
message_write(«Order status is » + order[«status»]);
if (order[«status»] == OS_MATCHED) {
if (timer1)
{
delTimer(timer1);
timer1 = 0;
signal::outputMultiple(«Timer1 was killed «);
message_write(«Timer1 was killed «);
}
if (price_at_start == 0)
{
price_at_start = order[«price»];
}
orders_count += 1;
signal::outputMultiple(«ORDERS_COUNT is now » + orders_count);
message_write(«ORDERS_COUNT is now » + orders_count);
if (orders_count >= orders_count_limit)
{
stop_algoritm = true;
}
trnid_write(id);
saveTrade(order);
if (stop_algoritm == true)
{
if (timer1)
{
delTimer(timer1);
timer1 = 0;
signal::outputMultiple(«Timer1 was killed «);
message_write(«Timer1 was killed «);
}
signal::alert(«Trade was stoped»);
message_write(«Trade was stoped»);
}
else
{
set_order(order);
}
}
}
//Функция обработки события на совершение сделки
function onTrade(var id)
{
orders_for_interval += 1;
}
//Функция на события срабатывания стоп-заявки
function onStopOrder(var id)
{
signal::outputMultiple(«OnStopOrder is activated»);
message_write(«OnStopOrder is activated»);
var order = getStopOrder(id);
if (order[«status»] == OS_MATCHED) {
if (timer1)
{
delTimer(timer1);
signal::outputMultiple(«Timer1 was killed «);
message_write(«Timer1 was killed «);
}
trnid_write(id);
saveTrade(order);
signal::outputMultiple(«Start set_order «);
message_write(«Start set_order «);
set_order(order);
}
signal::outputMultiple(«OnStopOrder is end»);
message_write(«OnStopOrder is end»);
}
//Функция по поиску в стакане заявок с достаточным количеством лотов
//need_OP = 0 для покупки и 1 для продажи
function get_book_position(var need_OP, var trade_quantity, var lot_mult)
{
var count_to_check;
var i;
var price_to_sell;
var vol_to_sell;
var price_to_buy;
var vol_to_buy;
var checker;
var act_price;
act_price = close;
book.load();
//нужно купить
if (need_OP == 0)
{
count_to_check = book.getBidPosCount();
}
//нужно продать
if (need_OP == 1)
{
count_to_check = book.getAskPosCount();
}
i = 1;
if (step_book > 0)
{
i = step_book;
}
signal::outputMultiple(«START calc. Num LOTS » + trade_quantity * lot_mult);
message_write(«START calc. Num LOTS » + trade_quantity * lot_mult);
while (i <= count_to_check-1) {
if (need_OP == 0)
{
price_to_sell = book.getAskPrice(i);
vol_to_sell = book.getAskVolume(i);
signal::outputMultiple(«PTS » + price_to_sell);
message_write(«PTS » + price_to_sell);
signal::outputMultiple(«VTS » + vol_to_sell);
message_write(«VTS » + vol_to_sell);
checker = (act_price <= price_to_sell) and (vol_to_sell>= trade_quantity * lot_mult);
signal::outputMultiple(«CHECKER » + checker);
message_write(«CHECKER » + checker);
if ((act_price <= price_to_sell) and (vol_to_sell >= trade_quantity * lot_mult))
{
signal::outputMultiple(«FIND solution » + i);
message_write(«FIND solution » + i);
i = count_to_check;
signal::outputMultiple(«END calc «);
message_write(«END calc «);
return price_to_sell;
}
else
{
i += 1;
}
}
if (need_OP == 1)
{
price_to_buy = book.getBidPrice(i);
vol_to_buy = book.getBidVolume(i);
signal::outputMultiple(«PTB » + price_to_buy);
message_write(«PTB » + price_to_buy);
signal::outputMultiple(«VTB » + vol_to_buy);
message_write(«VTB » + vol_to_buy);
checker = (act_price >= price_to_buy) and (vol_to_buy >= trade_quantity * lot_mult);
signal::outputMultiple(«CHECKER » + checker);
message_write(«CHECKER » + checker);
if ((act_price >= price_to_buy) and (vol_to_buy >= trade_quantity * lot_mult))
{
signal::outputMultiple(«FIND solution » + i);
message_write(«FIND solution » + i);
i = count_to_check;
signal::outputMultiple(«END calc «);
message_write(«END calc «);
return price_to_buy;
}
else
{
i += 1;
}
}
}
}
//Функция срабатывает на событие таймера 1, т.е. после каждого интервала таймера. Основная функция нашего робота
function onTimer1()
{
signal::outputMultiple(«OnTimer1 is start»);
message_write(«OnTimer1 is start»);
var order = new_object(«array»);
var order_ = new_object(«hash»);
var size_o;
var trade_price;
var trade_quantity;
var trade_orderno;
var trade_operation;
var act_price;
var i;
var j;
var price_to_buy;
var price_to_sell;
var vol_to_buy;
var vol_to_sell;
var count_to_buy;
var count_to_sell;
var checker;
var rl;
var sl;
var nl;
var trnid;
var check_success;
var len_str;
var lot_mult = 2;
var flow_balance;
var check_status;
var client_data = getClientLimits(getClient());
if (price_tracking == 1)
{
//Обработка следящей стратегии
signal::outputMultiple(«Puse_tracking_strategy » + use_tracking_strategy);
message_write(«Puse_tracking_strategy » + use_tracking_strategy);
if (use_tracking_strategy == 1)
{
summ_timer += time_shift_second;
if ((summ_timer < (tracking_interval_in_h * 3600) ) and (orders_for_interval >= orders_count_for_tracking))
{
procent_profit = procent_profit * noise_koeff;
if (procent_profit > 1)
{
procent_profit = 1;
}
//summ_timer = 0;
orders_for_interval = 0;
}
if ((summ_timer == (tracking_interval_in_h * 3600) ) )
{
if ((orders_for_interval <= orders_count_for_tracking))
{
procent_profit = procent_profit / noise_koeff;
}
summ_timer = 0;
orders_for_interval = 0;
}
signal::outputMultiple(«orders_for_interval » + orders_for_interval);
message_write(
«orders_for_interval » + orders_for_interval);
signal::outputMultiple(«summ_timer » + summ_timer);
message_write(«summ_timer » + summ_timer);
signal::outputMultiple(«tracking_interval_in_h » + tracking_interval_in_h * 3600);
message_write(«tracking_interval_in_h » + tracking_interval_in_h * 3600);
signal::outputMultiple(«Procent_profit » + procent_profit);
message_write(«Procent_profit » + procent_profit);
}
order = getAllTradeIDsBySec();
size_o = order.size();
size_o = getTrade(order[size_o-1]);
trade_price = size_o[«price»];
//trade_quantity = size_o[«quantity»];
//trade_quantity = get_number_of_lots(close);
trade_quantity = n_lots;
rl = getLotSize();
trade_orderno = size_o[«orderno»];
trade_operation = size_o[«operation»];
signal::outputMultiple(«START_balance » + start_balance);
message_write(«START_balance » + start_balance);
signal::outputMultiple(«Trade_price » + trade_price);
message_write(«Trade_price » + trade_price);
if (size_o[«operation»] == OP_SELL)
{
flow_balance = getMoneyBalance() — trade_quantity * rl * close;
//flow_balance = getMoneyBalance();
}
else{
flow_balance = getMoneyBalance() + trade_quantity * rl * close;
}
signal::outputMultiple(«Trade quantity » + trade_quantity);
message_write(«Trade quantity » + trade_quantity);
signal::outputMultiple(«FLOW_balance » + flow_balance);
message_write(«FLOW_balance » + flow_balance);
sl = trade_quantity * rl * price_at_start;
signal::outputMultiple(«summ_in_trade » + sl);
message_write(«summ_in_trade » + sl);
signal::outputMultiple(«price_at_start » + price_at_start);
message_write(«price_at_start » + price_at_start);
flow_profit = (flow_balance — start_balance) / (sl) * 100;
signal::outputMultiple(«flow_balance » + flow_balance);
message_write(«flow_balance » + flow_balance);
signal::outputMultiple(«start_balance » + start_balance);
message_write(«start_balance » + start_balance);
signal::outputMultiple(«sl » + sl);
message_write(«sl » + sl);
//алгоритм проверки уровня убытка
if (cycle_i == 0)
{
cycle_start_value = flow_profit;
}
if (loss_cycle > 0)
{
cycle_i += 1;
}
if ((cycle_i == loss_cycle) and (loss_cycle > 0))
{
cycle_end_value = flow_profit;
// если убыток более чем на 25% (loss_procent) велик, то переворачиваемся
if (((abs(cycle_end_value / cycle_start_value — 1)) >= (loss_procent)) and (cycle_end_value < 0))
{
//инициируем переворот
cycle_direction = 1;
signal::outputMultiple(«cycle_direction»);
message_write(«cycle_direction»);
}
cycle_i = 0;
}
signal::outputMultiple(«FLOW_profit » + flow_profit);
message_write(«FLOW_profit » + flow_profit);
if (flow_profit >= wish_profit_in_procent ) {
lot_mult = 1;
stop_algoritm = true;
signal::outputMultiple(«FLOW_profit is equal Wish _profit » + flow_profit);
message_write(«FLOW_profit is equal Wish _profit » + flow_profit);
}
// Заявка на продажу
if (trade_operation == OP_SELL) {
signal::outputMultiple(«OP is SELL «);
message_write(«OP is SELL «);
signal::outputMultiple(«BEGIN flow_price » + flow_price);
message_write(«BEGIN flow_price » + flow_price);
if (flow_price > 0)
{
if (close < flow_price)
{
flow_price = close;
signal::outputMultiple(«New flow_price «);
message_write(«New flow_price «);
}
}
else
{
flow_price = trade_price;
signal::outputMultiple(«Trade flow_price «);
message_write(«Trade flow_price «);
}
signal::outputMultiple(«CLOSE » + close);
message_write(«CLOSE » + close);
i = flow_price*(1 + procent_profit/100);
signal::outputMultiple(«CLOSE-FLOW » + i);
message_write(«CLOSE-FLOW » + i);
if ((close > flow_price * (1 + procent_profit/100)) or (stop_algoritm) or (cycle_direction))
{
if (stop_algoritm)
{
signal::outputMultiple(«COND to sell. STOP is activated»);
message_write(«COND to sell. STOP is activated»);
}
else
{
signal::outputMultiple(«COND to sell»);
message_write(«COND to sell»);
}
//на случай сбоя при обработке сделки
j = 0;
check_success = false;
while (check_success == false)
{
price_to_sell = get_book_position(0, trade_quantity, lot_mult);
signal::outputMultiple(«Trade quantity » + trade_quantity);
message_write(«Trade quantity » + trade_quantity);
signal::outputMultiple(«END calc «);
message_write(«END calc «);
if (orders_count + 1 == orders_count_limit)
{
lot_mult = 1;
}
order_[«operation»] = OP_BUY;
order_[«price»] = price_to_sell;
order_[«quantity»] = trade_quantity * lot_mult;
order_[«usecredit»] = true;
signal::outputMultiple(«Trade quantity * LOT_Mult » + order_[«quantity»] );
message_write(«Trade quantity * LOT_Mult » + order_[«quantity»] );
trade_action::cancelAllOrders();
if ((order_[«usecredit»]) or (lot_mult == 1))
{
signal::outputMultiple(«Usecredit is allowed «);
message_write(«Usecredit is allowed «);
trnid = trade_action::transactMultiple(order_);
signal::outputMultiple(«Trade is start TRNID » + trnid);
message_write(«Trade is start TRNID » + trnid);
}
else
{
order_[«quantity»] = trade_quantity;
signal::outputMultiple(«Usecredit is not allowed «);
message_write(«Usecredit is not allowed «);
trnid = trade_action::transactMultiple(order_);
trnid = trade_action::transactMultiple(order_);
signal::outputMultiple(«Trade is start TRNID » + trnid);
message_write(«Trade is start TRNID » + trnid);
}
signal::outputMultiple(«Trying nom. » + j);
message_write(«Trying nom. » + j);
j += 1;
len_str = as_number(trnid);
len_str = strlen(as_string(len_str));
if ((len_str > 0) or (j > 3))
{
check_success = true;
signal::outputMultiple(«LENGTH TRNID » + len_str);
message_write(«LENGTH TRNID » + len_str);
signal::outputMultiple(«check_success » + check_success );
message_write(«check_success » + check_success );
}
else
{
step_book = j + 1;
}
}
step_book = 0;
flow_price = 0;
signal::outputMultiple(«FIND to sell «);
message_write(«FIND to sell «);
signal::outputMultiple(«price_to_sell » + price_to_sell);
message_write(«price_to_sell » + price_to_sell);
signal::outputMultiple(«vol_to_sell » + vol_to_sell);
message_write(«vol_to_sell » + vol_to_sell);
}
}
if (trade_operation == OP_BUY) {
if (stop_algoritm)
{
signal::outputMultiple(«OP is BUY. STOP is activated»);
message_write(«OP is BUY. STOP is activated»);
}
else
{
signal::outputMultiple(«OP is BUY»);
message_write(«OP is BUY»);
}
signal::outputMultiple(«BEGIN flow_price » + flow_price);
message_write(«BEGIN flow_price » + flow_price);
if (flow_price > 0)
{
if (close > flow_price)
{
flow_price = close;
signal::outputMultiple(«New flow_price «);
message_write(«New flow_price «);
}
}
else
{
flow_price = trade_price;
signal::outputMultiple(«Trade flow_price «);
message_write(«Trade flow_price «);
}
signal::outputMultiple(«CLOSE » + close);
message_write(«CLOSE » + close);
i = flow_price/(1 + procent_profit/100);
signal::outputMultiple(«CLOSE-FLOW » + i);
message_write(«CLOSE-FLOW » + i);
if ((close < flow_price/(1 + procent_profit/100)) or (stop_algoritm) or (cycle_direction))
{
signal::outputMultiple(«COND to buy «);
message_write(«COND to buy «);
//на случай сбоя при обработке сделки
j = 0;
check_success = false;
while (check_success == false)
{
price_to_buy = get_book_position(1, trade_quantity, lot_mult);
if (orders_count + 1 == orders_count_limit)
{
lot_mult = 1;
}
order_[«operation»] = OP_SELL;
order_[«price»] = price_to_buy;
order_[«quantity»] = trade_quantity * lot_mult;
order_[«usecredit»] = true;
signal::outputMultiple(«Trade quantity * LOT_Mult » + order_[«quantity»] );
message_write(«Trade quantity * LOT_Mult » + order_[«quantity»]);
trade_action::cancelAllOrders();
if ((order_[«usecredit»]) or (lot_mult == 1))
{
signal::outputMultiple(«Usecredit is allowed «);
message_write(«Usecredit is allowed «);
trnid = trade_action::transactMultiple(order_);
signal::outputMultiple(«Trade is start TRNID » + trnid);
message_write(«Trade is start TRNID » + trnid);
}
else
{
order_[«quantity»] = trade_quantity;
signal::outputMultiple(«Usecredit is not allowed «);
message_write(«Usecredit is not allowed «);
trnid = trade_action::transactMultiple(order_);
trnid = trade_action::transactMultiple(order_);
signal::outputMultiple(«Trade is start TRNID » + trnid);
message_write(«Trade is start TRNID » + trnid);
}
signal::outputMultiple(«Trying nom. » + j);
message_write(«Trying nom. » + j);
j += 1;
len_str = as_number(trnid);
len_str = strlen(as_string(len_str));
if ((len_str > 0) or (j > 3))
{
check_success = true;
signal::outputMultiple(«LENGTH TRNID » + len_str);
message_write(«LENGTH TRNID » + len_str);
signal::outputMultiple(«check_success » + check_success );
message_write(«check_success » + check_success);
}
else
{
step_book = j + 1;
}
}
step_book = 0;
flow_price = 0;
//trade_action::sellMultiple(trade_quantity * lot_mult, ::lots, price_to_buy);
signal::outputMultiple(«FIND to buy «);
message_write(«FIND to buy «);
signal::outputMultiple(«price_to_buy » + price_to_buy);
message_write(«price_to_buy » + price_to_buy);
}
}
signal::outputMultiple(«FLOW_Price » + flow_price);
message_write(«FLOW_Price » + flow_price);
}
if (cycle_direction)
{
cycle_direction = 0;
}
signal::outputMultiple(«OnTimer1 is end»);
message_write(«OnTimer1 is end»);
}
//Функция обработки событй второго таймера
function onTimer2()
{
var nl;
var n_active = 0;
var sec_array = new_object(«array»);
var order_array = new_object(«array»);
var order = new_object(«hash»);
var size_a;
var size_o;
var nom_order;
var trnid;
var rl;
var get_price;
var timer_cond = false;
if (isTradingAllowed())
{
signal::outputMultiple(«Timer2 start»);
message_write(«Timer2 start»);
n_active = getSecBalance();
n_lots = get_number_of_lots(close);
nl = n_lots;
if (n_active == 0)
{
start_balance = getMoneyBalance();
if ((close — timer2_price) >= 0)
{
get_price = get_book_position(0, nl, 1);
trnid = trade_action::buy(nl, ::lots, get_price);
}
else
{
get_price = get_book_position(1, nl, 1);
trnid = trade_action::sell(nl, ::lots, get_price);
}
signal::outputMultiple(«Get_Price » + get_price);
message_write(«Get_Price » + get_price);
signal::outputMultiple(«nl » + nl);
message_write(«nl » + nl);
signal::outputMultiple(«trnid » + trnid);
message_write(«trnid » + trnid);
delTimer(timer2);
timer2 = 0;
signal::outputMultiple(«Timer2 was killed «);
message_write(«Timer2 was killed «);
}
else
{
signal::outputMultiple(«SecBalance» + n_active);
message_write(«SecBalance» + n_active);
order_array = getAllOrderIDs();
size_o = order_array.size();
signal::outputMultiple(«OrderSize » + size_o);
message_write(«OrderSize » + size_o);
size_o = getOrder(order_array[size_o-1]);
nom_order = size_o[«orderno»];
signal::outputMultiple(«Order No» + nom_order);
message_write(«Order No» + nom_order);
delTimer(timer2);
timer2 = 0;
signal::outputMultiple(«Timer2 was killed «);
message_write(«Timer2 was killed «);
timer_cond = true;
sec_array = getAllTradeIDsBySec();
size_a = sec_array.size();
signal::outputMultiple(«SecSize » + size_a);
message_write(«SecSize » + size_a);
size_a = getTrade(sec_array[size_a-1]);
signal::outputMultiple(«Trade Nomber » + size_a[«tradeno»]);
message_write(«Trade Nomber » + size_a[«tradeno»]);
signal::outputMultiple(«Trade Price » + size_a[«price»]);
message_write(«Trade Price » + size_a[«price»]);
price_at_start = size_a[«price»];
if (start_balance == 0)
{
rl = getLotSize();
if (size_a[«operation»] == OP_SELL)
{
start_balance = getMoneyBalance() — nl * rl * price_at_start;
}
else{
start_balance = getMoneyBalance() + nl * rl * price_at_start;
}
}
timer1 = setTimer(«onTimer1», time_shift_second * 1000, TIMER_PERIODICALLY);
}
signal::outputMultiple(«Start Balance » + start_balance);
message_write(«Start Balance » + start_balance);
}
}
//Добавим функцию останова робота при нажатии одновременно левого SHIFT и клавиши С. Сработает, если в TRANSAQ активно окно с графиком, где работаем наш скрипт робота
function onKeyDown(var key)
{
if (isKeyPressed(KEY_LSHIFT))
{
if (key == chr2num(«C»))
{
delTimer(timer1);
delTimer();
timer1 = 0;
signal::alert(«Program was stopped!»);
message_write(«Program was stopped!»);
}
}
}
//Функция в нашем роботе не задействована, хотя через нее можно выводить какую-либо информацию
function calc()
{
line[0] = 0;
}