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

feature: breaking changes and new StopOrder functions #284

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Examples/QuikSharpDemo/FormMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ private async Task CallCommand()
{
decimal priceInOrder = Math.Round(tool.LastPrice - tool.LastPrice / 20, tool.PriceAccuracy);
AppendText2TextBox(textBoxLogsWindow, "Выставляем заявку на покупку, по цене:" + priceInOrder + " ..." + Environment.NewLine);
order = await _quik.Orders.SendLimitOrder(tool.ClassCode, tool.SecurityCode, tool.AccountID, Operation.Buy, priceInOrder, 1).ConfigureAwait(false);
order = await _quik.Orders.SendLimitOrder(tool.ClassCode, tool.SecurityCode, tool.AccountID, clientCode, Operation.Buy, priceInOrder, 1).ConfigureAwait(false);
if (order.OrderNum > 0)
{
AppendText2TextBox(textBoxLogsWindow, "Заявка выставлена. ID транзакции - " + order.TransID + Environment.NewLine);
Expand All @@ -388,7 +388,7 @@ private async Task CallCommand()
{
decimal priceInOrder = Math.Round(tool.LastPrice + tool.Step * 5, tool.PriceAccuracy);
AppendText2TextBox(textBoxLogsWindow, "Выставляем заявку на покупку, по цене:" + priceInOrder + " ..." + Environment.NewLine);
long transactionID = (await _quik.Orders.SendLimitOrder(tool.ClassCode, tool.SecurityCode, tool.AccountID, Operation.Buy, priceInOrder, 1).ConfigureAwait(false)).TransID;
long transactionID = (await _quik.Orders.SendLimitOrder(tool.ClassCode, tool.SecurityCode, tool.AccountID, clientCode, Operation.Buy, priceInOrder, 1).ConfigureAwait(false)).TransID;
if (transactionID > 0)
{
AppendText2TextBox(textBoxLogsWindow, "Заявка выставлена. ID транзакции - " + transactionID + Environment.NewLine);
Expand Down Expand Up @@ -419,7 +419,7 @@ private async Task CallCommand()
{
decimal priceInOrder = Math.Round(tool.LastPrice + tool.Step * 5, tool.PriceAccuracy);
AppendText2TextBox(textBoxLogsWindow, "Выставляем рыночную заявку на покупку..." + Environment.NewLine);
long transactionID = (await _quik.Orders.SendMarketOrder(tool.ClassCode, tool.SecurityCode, tool.AccountID, Operation.Buy, 1).ConfigureAwait(false)).TransID;
long transactionID = (await _quik.Orders.SendMarketOrder(tool.ClassCode, tool.SecurityCode, tool.AccountID, clientCode, Operation.Buy, 1).ConfigureAwait(false)).TransID;
if (transactionID > 0)
{
AppendText2TextBox(textBoxLogsWindow, "Заявка выставлена. ID транзакции - " + transactionID + Environment.NewLine);
Expand Down
9 changes: 8 additions & 1 deletion src/QuikSharp/DataStructures/StopOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ public int Flags
[JsonProperty("class_code")]
public string ClassCode { get; set; }

/// <summary>
/// Дата и время выставления стоп-заявки
/// </summary>
[JsonProperty("order_date_time")]
public QuikDateTime Datetime { get; set; }


/// <summary>
/// Отступ от min/max
/// </summary>
Expand Down Expand Up @@ -288,4 +295,4 @@ public enum Operation
Buy,
Sell
}
}
}
3 changes: 2 additions & 1 deletion src/QuikSharp/DataStructures/Transaction/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ internal void OnTransReplyCall(TransactionReply reply)
/// <summary>
/// TransactionReply
/// </summary>
public TransactionReply TransactionReply { get; set; }
volatile TransactionReply _transactionReply;
public TransactionReply TransactionReply { get => _transactionReply; set { _transactionReply = value; } }

/// <summary>
/// Функция вызывается терминалом QUIK при получении новой заявки или при изменении параметров существующей заявки.
Expand Down
107 changes: 82 additions & 25 deletions src/QuikSharp/OrderFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ public async Task<long> CreateOrder(Order order)
/// <param name="operation">Операция заявки (покупка/продажа)</param>
/// <param name="price">Цена заявки</param>
/// <param name="qty">Количество (в лотах)</param>
public async Task<Order> SendLimitOrder(string classCode, string securityCode, string accountID, Operation operation, decimal price, int qty)
public async Task<Order> SendLimitOrder(string classCode, string securityCode, string accountID, string clientCode, Operation operation, decimal price, int qty)
{
return await SendOrder(classCode, securityCode, accountID, operation, price, qty, TransactionType.L).ConfigureAwait(false);
return await SendOrder(classCode, securityCode, accountID, clientCode, operation, price, qty, TransactionType.L).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -67,11 +67,12 @@ public async Task<Order> SendLimitOrder(string classCode, string securityCode, s
/// <param name="classCode">Код класса инструмента</param>
/// <param name="securityCode">Код инструмента</param>
/// <param name="accountID">Счет клиента</param>
/// <param name="clientCode">Код клиента</param>
/// <param name="operation">Операция заявки (покупка/продажа)</param>
/// <param name="qty">Количество (в лотах)</param>
public async Task<Order> SendMarketOrder(string classCode, string securityCode, string accountID, Operation operation, int qty)
public async Task<Order> SendMarketOrder(string classCode, string securityCode, string accountID, string clientCode, Operation operation, int qty)
{
return await SendOrder(classCode, securityCode, accountID, operation, 0, qty, TransactionType.M).ConfigureAwait(false);
return await SendOrder(classCode, securityCode, accountID, clientCode, operation, 0, qty, TransactionType.M).ConfigureAwait(false);
}

/// <summary>
Expand All @@ -80,15 +81,14 @@ public async Task<Order> SendMarketOrder(string classCode, string securityCode,
/// <param name="classCode">Код класса инструмента</param>
/// <param name="securityCode">Код инструмента</param>
/// <param name="accountID">Счет клиента</param>
/// <param name="clientCode">Код клиента</param>
/// <param name="operation">Операция заявки (покупка/продажа)</param>
/// <param name="price">Цена заявки</param>
/// <param name="qty">Количество (в лотах)</param>
/// <param name="orderType">Тип заявки (L - лимитная, M - рыночная)</param>
async Task<Order> SendOrder(string classCode, string securityCode, string accountID, Operation operation, decimal price, int qty, TransactionType orderType)
async Task<Order> SendOrder(string classCode, string securityCode, string accountID, string clientCode, Operation operation, decimal price, int qty, TransactionType orderType)
{
long res = 0;
bool set = false;
Order order_result = new Order();
Transaction newOrderTransaction = new Transaction
{
ACTION = TransactionAction.NEW_ORDER,
Expand All @@ -98,48 +98,80 @@ async Task<Order> SendOrder(string classCode, string securityCode, string accoun
QUANTITY = qty,
OPERATION = operation == Operation.Buy ? TransactionOperation.B : TransactionOperation.S,
PRICE = price,
TYPE = orderType
TYPE = orderType,
CLIENT_CODE = clientCode
};
try
{
res = await Quik.Trading.SendTransaction(newOrderTransaction).ConfigureAwait(false);
Thread.Sleep(500);
Thread.Sleep(50);
Console.WriteLine("res: " + res);
}
catch
{
//ignore
}

while (!set)
{
if (res > 0)
if(res < 0)
return new Order
{
try
{
order_result = await Quik.Orders.GetOrder_by_transID(classCode, securityCode, res).ConfigureAwait(false);
}
catch
RejectReason = newOrderTransaction.ErrorMessage,
ClassCode = classCode,
SecCode = securityCode,
Account = accountID,
ClientCode = clientCode,
Operation = operation,
Price = price,
Quantity = qty
};

while (true)
{
if (newOrderTransaction.TransactionReply != null && newOrderTransaction.TransactionReply.ErrorSource != 0)
return new Order
{
order_result = new Order {RejectReason = "Неудачная попытка получения заявки по ID-транзакции №" + res};
}
RejectReason =
newOrderTransaction.TransactionReply.ResultMsg
?? $"Transaction {res} error: code {newOrderTransaction.TransactionReply.ErrorCode}, source {newOrderTransaction.TransactionReply.ErrorSource}",
ClassCode = classCode,
SecCode = securityCode,
Account = accountID,
ClientCode = clientCode,
Operation = operation,
Price = price,
Quantity = qty
};

try
{
var result = await Quik.Orders.GetOrder_by_transID(classCode, securityCode, res).ConfigureAwait(false);
if (result != null)
return result;
}
else
catch(Exception e)
{
if (order_result != null) order_result.RejectReason = newOrderTransaction.ErrorMessage;
else order_result = new Order {RejectReason = newOrderTransaction.ErrorMessage};
return new Order
{
RejectReason = $"Неудачная попытка получения заявки по ID-транзакции №{res}, {e.Message}",
ClassCode = classCode,
SecCode = securityCode,
Account = accountID,
ClientCode = clientCode,
Operation = operation,
Price = price,
Quantity = qty
};
}

if (order_result != null && (order_result.RejectReason != "" || order_result.OrderNum > 0)) set = true;
Thread.Sleep(10);
}

return order_result;
}

/// <summary>
/// Отмена заявки.
/// </summary>
/// <param name="order">Информация по заявке, которую требуется отменить.</param>
/// <returns>Номер транзакции</returns>
public async Task<long> KillOrder(Order order)
{
Transaction killOrderTransaction = new Transaction
Expand All @@ -152,6 +184,31 @@ public async Task<long> KillOrder(Order order)
return await Quik.Trading.SendTransaction(killOrderTransaction).ConfigureAwait(false);
}

/// <summary>
/// Отмена заявки с ожиданием завершения транзакции.
/// </summary>
/// <param name="order">Информация по заявке, которую требуется отменить.</param>
/// <returns>Результат выполнения транзакции.</returns>
public async Task<TransactionReply> KillOrderEx(Order order)
{
Transaction killOrderTransaction = new Transaction
{
ACTION = TransactionAction.KILL_ORDER,
CLASSCODE = order.ClassCode,
SECCODE = order.SecCode,
ORDER_KEY = order.OrderNum.ToString()
};

var res = await Quik.Trading.SendTransaction(killOrderTransaction).ConfigureAwait(false);
if (res < 0)
return null;

while (killOrderTransaction.TransactionReply == null)
Thread.Sleep(10);

return killOrderTransaction.TransactionReply;
}

/// <summary>
/// Возвращает заявку из хранилища терминала по её номеру.
/// На основе: http://help.qlua.org/ch4_5_1_1.htm
Expand Down
11 changes: 6 additions & 5 deletions src/QuikSharp/QuikEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -483,12 +483,13 @@ internal void OnTransReplyCall(TransactionReply reply)
OnTransReply?.Invoke(reply);

// invoke event specific for the transaction
if (string.IsNullOrEmpty(reply.Comment)) //"Initialization user successful" transaction doesn't contain comment
return;

if (QuikService.Storage.Contains(reply.Comment))

var transId = reply.TransID.ToString();

if (QuikService.Storage.Contains(transId))
{
var tr = QuikService.Storage.Get<Transaction>(reply.Comment);
var tr = QuikService.Storage.Get<Transaction>(transId);
lock (tr)
{
tr.OnTransReplyCall(reply);
Expand All @@ -501,4 +502,4 @@ internal void OnTransReplyCall(TransactionReply reply)
}
}
}
}
}
4 changes: 2 additions & 2 deletions src/QuikSharp/QuikService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ internal int GetUniqueTransactionId()
}
else
{
if (newId >= 2147483638) newId = 100;
if (newId >= 2147483637 || newId < 1) newId = 100;
newId++;
}

Expand Down Expand Up @@ -891,4 +891,4 @@ internal async Task<TResponse> Send<TResponse>(IMessage request, int timeout = 0
return (response as TResponse);
}
}
}
}
Loading