Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Надежный способ получать объект TransactionReply и id выставленного ордера по id транзакции #299

Open
MrJimm opened this issue Jul 22, 2021 · 0 comments

Comments

@MrJimm
Copy link

MrJimm commented Jul 22, 2021

В своем приложении для автоматизации мне нужно получать объект TransactionReply ответа на транзакцию выставления нового стоп ордера, с ее статусом, и id только что выставленного ордера.
Сейчас я делаю это через вот такую странную конструкцию, потому что способа лучше пока не нашел:

Подписываюсь на событие OnTransReply и складываю в конкарент очередь все приходящие ответы на транзакцию:

private void Events_OnTransReply(QuikSharp.DataStructures.Transaction.TransactionReply transReply)
{
    _transResponses[transReply.TransID] = transReply;
}

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

var createOrderRes = _quik.StopOrders.CreateStopOrder(order).Result;

//await for transaction response
var transId = Math.Abs(createOrderRes);
var getTransRespTimeoutMs = 400;
var getTransRespIterations = 40;
TransactionReply transResp = null;

for (var i = 0; i < getTransRespIterations; ++i)
{
    if (_transResponses.ContainsKey(transId))
    {
        _transResponses.TryRemove(transId, out TransactionReply res);
        transResp = res;
        break;
    }
    Thread.Sleep(getTransRespTimeoutMs);
}
  1. Тут встречается первая проблема:
    Как видно, таймаут и число попыток достаточно больше, но все равно, в редких случаях я встречаю ситуации, когда transResp остается нулевым - а это значит что, похоже, до этого в очередь в коллбэке события не положили ответ на транзакцию с id == Math.Abs(createOrderRes)

  2. Вторая проблема более странная и встречается тоже внезапно, и тоже раз в пару дней (по ощущениям - когда выставляешь несколько ордеров последовательно, с небольшим таймаутом между ними): в получаемом по transId ордере неверный secCode инструмента!

Как я это обнаруживаю:
Если transactionResponse пришел с хорошим кодом и без ошибок, я дальше получаю по нему ордер таким образом:

var newOrder = this.GetNewStopOrderByTransactionId(transId).Result;

Где:

private async Task<QuikSharp.DataStructures.StopOrder> GetNewStopOrderByTransactionId(long transId)
{
    var attemptsCount = 20;
    Thread.Sleep(100);

    var stopOrder = await GetStopOrderByTransactionId(transId);
    if (stopOrder != null)
        return stopOrder;

    //if stop order wasn't found
    for (var i = 2; i <= attemptsCount; ++i)
    {
        Thread.Sleep(500);
        Log($"Attempt {i}/{attemptsCount} to retrieve new stop order for transaction {transId}...");
        stopOrder = await GetStopOrderByTransactionId(transId);
        if (stopOrder != null)
            return stopOrder;
    }

    return null;
}

И, соответственно:

private async Task<QuikSharp.DataStructures.StopOrder> GetStopOrderByTransactionId(long transId)
{
    var stopOrders = await _quik.StopOrders.GetStopOrders();
    if (stopOrders != null)
    {
        var stopOrder = stopOrders.FirstOrDefault(x => x.TransId == transId);
        if (stopOrder != null)
            return stopOrder;
    }
    return null;
} 

И вот тут начинается проблема: я начал ловить ситуации, когда SecCode инструмента в ордере, объект которого я отправил на выставление в метод _quik.StopOrders.CreateStopOrder(order).Result; либы не совпадает с secCode ордера, который я получил по this.GetNewStopOrderByTransactionId(transId) (!!!)
То есть периодически выполняется return в этой проверке:

if (newOrder.SecCode != newStopOrder.Ticker)
{
    var msg = $"Placed order secCode {newOrder.SecCode} is not equal to requested ticker {newStopOrder.Ticker}. Check by transaction ids: awaited to createdOrderRes {createOrderRes} transaction id {transId} but obtained new order with trans id {newOrder.TransId}";
    Log($"ERROR! {msg}");
    return new PlaceNewOrderResult
    {
        IsError = true,
        State = PlaceNewOrderResult.ResultState.GeneralError,
        Message = msg
    };
}

Как будто бы, если последовательно выставляются несколько ордеров по разным инструментам, то транзакции по ним могут перепутаться. Проверяя свой код, я пока не нашел в нем ошибку, которая могла бы приводить к такому поведению.
Хотел бы услышать, сталкивался ли кто-то еще с таким поведением? И буду благодарен, если сможете подсказать более простой и надежный способ получать выставленный ордер и данные TransactionReply по id транзакции.

@MrJimm MrJimm changed the title Надежный способ получать id выставленного ордера по id транзакции Надежный способ получать объект TransactionReply и id выставленного ордера по id транзакции Jul 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant