forked from QuantBox/QuantBox.APIProvider
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQuoteMap.cs
More file actions
156 lines (137 loc) · 6.18 KB
/
Copy pathQuoteMap.cs
File metadata and controls
156 lines (137 loc) · 6.18 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using XAPI;
using SmartQuant;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SQ = SmartQuant;
namespace QuantBox.APIProvider.Single
{
class QuoteMap : BaseMap
{
private OrderMap orderMap;
private ConcurrentDictionary<string, QuoteRecord> pendingOrders; // 新单
private Dictionary<string, QuoteRecord> workingOrders; // 挂单
private Dictionary<int, string> orderIDs; // 撤单时映射
private ConcurrentDictionary<string, QuoteRecord> pendingCancels; // 撤单拒绝时使用
public QuoteMap(Framework framework, SingleProvider provider,OrderMap orderMap):base(framework,provider)
{
this.orderMap = orderMap;
pendingOrders = new ConcurrentDictionary<string, QuoteRecord>();
workingOrders = new Dictionary<string, QuoteRecord>();
orderIDs = new Dictionary<int, string>();
pendingCancels = new ConcurrentDictionary<string, QuoteRecord>();
}
public void Clear()
{
pendingOrders.Clear();
workingOrders.Clear();
orderIDs.Clear();
pendingCancels.Clear();
orderMap.Clear();
}
public void EmitExecutionReport(QuoteRecord record, SQ.ExecType execType, SQ.OrderStatus orderStatus)
{
EmitExecutionReport(new OrderRecord(record.AskOrder), execType, orderStatus);
EmitExecutionReport(new OrderRecord(record.BidOrder), execType, orderStatus);
}
public void EmitExecutionReport(QuoteRecord record, SQ.ExecType execType, SQ.OrderStatus orderStatus, string text)
{
EmitExecutionReport(new OrderRecord(record.AskOrder), execType, orderStatus, text);
EmitExecutionReport(new OrderRecord(record.BidOrder), execType, orderStatus, text);
}
public void DoQuoteSend(QuoteField quote, ExecutionCommand command,Order askOrder,Order bidOrder)
{
//string askRef;
//string bidRef;
//provider._TdApi.SendQuote(ref quote,out askRef,out bidRef);
//if (askRef == null)
//{
// // 直接将单子拒绝
// EmitExecutionReport(new QuoteRecord(askOrder, bidOrder), SQ.ExecType.ExecRejected, SQ.OrderStatus.Rejected, "ErrorCode:");
//}
//else
//{
// this.pendingOrders.TryAdd(askRef, new QuoteRecord(askOrder, bidOrder));
//}
}
public void DoQuoteCancel(ExecutionCommand command)
{
string quoteId;
if (orderIDs.TryGetValue(command.Order.Id, out quoteId))
{
QuoteRecord record;
if (this.workingOrders.TryGetValue(quoteId, out record))
{
pendingCancels[quoteId] = record;
}
//string err;
//provider._TdApi.CancelQuote(quoteId,out err);
//if (!string.IsNullOrEmpty(err))
//{
// EmitExecutionReport(record, SQ.ExecType.ExecCancelReject, record.Status, "ErrorCode:" + err);
//}
}
}
public void Process(ref QuoteField quote)
{
// 所有的成交信息都不处理,交给TradeField处理
if (quote.ExecType == XAPI.ExecType.Trade)
return;
QuoteRecord record = null;
switch (quote.ExecType)
{
case XAPI.ExecType.New:
if (this.pendingOrders.TryRemove(quote.ID, out record))
{
this.workingOrders.Add(quote.ID, record);
this.orderIDs.Add(record.AskOrder.Id, quote.ID);
this.orderIDs.Add(record.BidOrder.Id, quote.ID);
orderMap.ProcessNew(ref quote, record);
// 这个地方可以跳过
//EmitExecutionReport(record, quote.ExecType, quote.Status);
}
break;
case XAPI.ExecType.Rejected:
if (this.pendingOrders.TryRemove(quote.ID, out record))
{
EmitExecutionReport(record, (SQ.ExecType)quote.ExecType, (SQ.OrderStatus)quote.Status, quote.Text());
}
else if (this.workingOrders.TryGetValue(quote.ID, out record))
{
// 比如说出现超出涨跌停时,先会到ProcessNew,所以得再多判断一次
workingOrders.Remove(quote.ID);
orderIDs.Remove(record.AskOrder.Id);
orderIDs.Remove(record.BidOrder.Id);
EmitExecutionReport(record, (SQ.ExecType)quote.ExecType, (SQ.OrderStatus)quote.Status, quote.Text());
}
break;
case XAPI.ExecType.Cancelled:
if (this.workingOrders.TryGetValue(quote.ID, out record))
{
workingOrders.Remove(quote.ID);
orderIDs.Remove(record.AskOrder.Id);
orderIDs.Remove(record.BidOrder.Id);
EmitExecutionReport(record, SQ.ExecType.ExecCancelled, SQ.OrderStatus.Cancelled);
}
break;
case XAPI.ExecType.PendingCancel:
if (this.workingOrders.TryGetValue(quote.ID, out record))
{
EmitExecutionReport(record, SQ.ExecType.ExecPendingCancel, SQ.OrderStatus.PendingCancel);
}
break;
case XAPI.ExecType.CancelReject:
if (this.pendingCancels.TryRemove(quote.ID, out record))
{
EmitExecutionReport(record, SQ.ExecType.ExecCancelReject, (SQ.OrderStatus)quote.Status, quote.Text());
}
break;
}
if(record != null)
record.Status = (SQ.OrderStatus)quote.Status;
}
}
}