Блог им. Bondiator

Вопрос по Луа 3 - работа циклов


Зарегистрировался для развития на форуме Арки и в разделе по программированию на Луа нашел код (https://forum.quik.ru/forum10/topic5664/)
Смысл в том, что автор хочет продавать актив поштучно пока в портфеле не останется какое-то количество бумаг.
На мой взгляд полезная вещь.
Когда я его попробовал на демо квике, то начались бесконечные продажи (как и у автора).
Судя по записям, проблема не решена.
Может кто подскажет как решить вопрос?

<code class="rainbow" data-language="lua">   while stopped == false do

      Quotes_1 = getQuoteLevel2("SPBFUT", "SRU0")

      Bid_Count_1 = tonumber(Quotes_1.bid_count)

      if Bid_Count_1>1 then
         aa= tonumber(Quotes_1.bid[Bid_Count_1].quantity)
         SetCell(Table, 1, 1, tostring(aa))
      end

      local asset = getFuturesHolding("SPBFUT", "SPBFUT****","SRU0",0).totalnet

      repeat

            if aa>1 and asset>0 then

               local ID_B_Order=10
               local OrderSell = {
                     ["ACTION"]="NEW_ORDER",
                     ["ACCOUNT"]= "SPBFUT****",
                            ["OPERATION"] = "S",
                     ["CLASSCODE"]="SPBFUT",
                            ["SECCODE"] = "SRU0",
                            ["PRICE"] = "0",
                     ["QUANTITY"] = tostring(1),
                     ["TRANS_ID"] = tostring(ID_B_Order),
                     ["TYPE"] = "M",
                     }
               local Err_Order = sendTransaction(OrderSell)
               message(Err_Order)
            end

            asset=asset-1

            sleep(1000)

      until asset==5<br />end</code>
  • обсудить на форуме:
  • Quik Lua
★2
16 комментариев
там же на форуме уже разжевали почему так. Зациклился while, которого у вас нет в вашем примере
avatar
Андрей К, видел. Вопрос как его расциклить с минимумом текста
Врач-бондиатОр, в вычислении asset учитывать ещё и открытые заявки по нему, которые наставились в предыдущих итерациях цикла
avatar
Андрей К, есть в примере, притаился сверху ))) только end для него нема
avatar
kachanov, это где вы увидали? End я могу добавить
Врач-бондиатОр, первая строка
<code class="rainbow" data-language="lua">   while stopped == false do
начало цикла 
while stopped == false do

P.S. только обычно такую конструкцию не используют
гораздо понятней while is_run do  end

avatar
Врач-бондиатОр, о, end тоже не сразу разглядел )) он есть!
в данном коде достаточно поставить после цикла repeat остановку while

типа
 stopped = true (или любое число или символ)
т.е. последняя строка примет вид
  until asset==5   stopped = true  end</code>
останется 5 бумаг, если все транзакции сработают. Если нужен контроль за их исполнением, то написали ниже как это делать
avatar

Алгоритм примерно такой:

1. Отправляем заявку на продажу. Скрипт запоминает trans_id этой заявки.

2. Через колбек OnOrder получаем информацию о всех заявках. Смотрим, когда у заявки с запомненным trans_id статус поменяется на «исполнена».

3. Как только заявка с запомненным trans_id исполнена, отправляем новую заявку

 
avatar
Chalyj7, то есть, если нужно продать 7 бумаг, то нужно отследить 7 заявок на продажу?
Врач-бондиатОр, да. Не имеет значения сколько заявок. Надо ждать исполнения отправленной заявки и только потом отправлять следующую.
avatar
Chalyj7, я могу это представить если заявки две (их можно в коде зафиксировать). А если количество задается переменной, то как быть?

Врач-бондиатОр, смотрите, тут уже писали, собираю все в кучу.

у Вас в коде

Quotes_1 = getQuoteLevel2(«SPBFUT», «SRU0»)

Bid_Count_1 = tonumber(Quotes_1.bid_count)

if Bid_Count_1>1 then
aa= tonumber(Quotes_1.bid[Bid_Count_1].quantity)
SetCell(Table, 1, 1, tostring(aa))
end

запрашиваете стакан и первую цену бида (но почему то только один раз)

local asset = getFuturesHolding(«SPBFUT», «SPBFUT****»,«SRU0»,0).totalnet

снова один раз запрашиваете количество бумаг

дальше 

repeat — until — он заходит в цикл в любом случае один раз… не понятно, почему именно этот вид цикла выбран… ну ладно...

что надо сделать:

1. завести еще одну переменную, в ней хранить номер (trans_id) отправляемой заявки. В Вашем коде каждой заявке Вы присваиваете один и тот же номер. Квик такое пропускает, но в этом нет смысла.

2. Добавить обработку колбека OnOrder, чтобы он сбрасывал в ноль хранимый номер.

т.е. код должне выглядеть примерно так:

local Active_Trans_Id = 0 — храним номер заявки тут
local ID_B_Order=10

while getFuturesHolding(«SPBFUT», «SPBFUT****»,«SRU0»,0).totalnet > 0

if Active_Trans_Id == 0 then -- 

Quotes_1 = getQuoteLevel2(«SPBFUT», «SRU0»)
Bid_Count_1 = tonumber(Quotes_1.bid_count)

if Bid_Count_1>1 then
aa= tonumber(Quotes_1.bid[Bid_Count_1].quantity)
SetCell(Table, 1, 1, tostring(aa))
end

if aa>1 then

local OrderSell = {
[«ACTION»]=«NEW_ORDER»,
[«ACCOUNT»]= «SPBFUT****»,
[«OPERATION»] = «S»,
[«CLASSCODE»]=«SPBFUT»,
[«SECCODE»] = «SRU0»,
[«PRICE»] = «0»,
[«QUANTITY»] = tostring(1),
[«TRANS_ID»] = tostring(ID_B_Order),
[«TYPE»] = «M»,
}
local Err_Order = sendTransaction(OrderSell)
Active_Trans_Id = ID_B_Order — заполняем переменную номером TRANS_ID
ID_B_Order = ID_B_Order + 1 — увеличивает TRANS_ID, чтобы он был разный для каждой заявки
message(Err_Order)
end
sleep(1000)
end

— где-то за пределами main
— добавьте обработку колбека OnOrder
function OnOrder(order)
if order == Active_Trans_Id and (тут надо найти вставить проверку, что заявка исполнена проверяя биты order.flags) then
Active_Trans_Id = 0 — обнуляем номер активной заявки
end
end


т.е. если Active_Trans_Id равен 0, но программа отправляет заявку и присваитвает переменной Active_Trans_Id номер заявки.

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

Колбек OnOrder смотрит, прошла ли заявка с номером Active_Trans_Id и если прошла, обнуляет Active_Trans_Id.

P.S. код писал в блокноте, не проверял. Под номером заявки, имею ввиде Trans_Id

 

 

avatar
т.е. там реально поменять порядок строк и добавить 5 новых строчек, чтобы все заработало. 

avatar
Chalyj7, спасибо! ) Как все непросто…
Цикл счётчик поставь
Просто каждый раз запрашивайте кол-во бумаг заново. Все.
На случай крайний поменяйте логику условия.
      repeat
          local asset = getFuturesHolding("SPBFUT", "SPBFUT****","SRU0",0).totalnet
          ****
      until asset==5
avatar

теги блога Врач-бондиатОр

....все тэги



UPDONW
Новый дизайн