├── .gitattributes
├── .gitignore
├── CTP.Brokers.xml
├── CTPZQ.Brokers.xml
├── LICENSE.txt
├── QuantBox.nlog
├── README.md
└── src
├── QuantBox.Helper.CTP
├── CTPAPI.cs
├── CTPQuote.cs
├── CTPTrade.cs
├── DataConvert.cs
├── Properties
│ └── AssemblyInfo.cs
├── QuantBox.Helper.CTP.Net35.csproj
├── QuantBox.Helper.CTP.Net40.csproj
├── QuantBox.Helper.CTPZQ.Net35.csproj
└── QuantBox.Helper.CTPZQ.Net40.csproj
├── QuantBox.OQ.CTP.sln
└── QuantBox.OQ.CTP
├── APIProvider.CTP.Connection.cs
├── APIProvider.CTP.MarketData.cs
├── APIProvider.CTP.Order.cs
├── APIProvider.CTP.Quote.cs
├── APIProvider.CTP.cs
├── APIProvider.ExecutionProvider.cs
├── APIProvider.InstrumentProvider.cs
├── APIProvider.MarketDataProvider.cs
├── APIProvider.Provider.cs
├── APIProvider.Settings.cs
├── APIProvider.SimulationMarketDataProvider.cs
├── AccountItem.cs
├── ApiContainer.cs
├── ApiWrapper.cs
├── BrokerItem.cs
├── DataRecord.cs
├── OrderMap.cs
├── OrderRecord.cs
├── Properties
├── AssemblyInfo.cs
└── DataSources
│ ├── BrokerItem.datasource
│ └── ServerItem.datasource
├── QuantBox.OQ.CTP.OQ3.csproj
├── QuantBox.OQ.CTP.QD.csproj
├── QuantBox.OQ.CTPZQ.OQ3.csproj
├── QuantBox.OQ.CTPZQ.QD.csproj
├── QuoteApiWrapper.cs
├── ServerItem.cs
├── ServersManagerForm.Designer.cs
├── ServersManagerForm.cs
├── ServersManagerForm.resx
├── ServersManagerTypeEditor.cs
├── TraderApiWrapper.cs
└── WinAPI.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text eol=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Visual Studio
3 | #################
4 |
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 |
8 | # User-specific files
9 | *.suo
10 | *.user
11 | *.sln.docstates
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Rr]elease/
16 | *_i.c
17 | *_p.c
18 | *.ilk
19 | *.meta
20 | *.obj
21 | *.pch
22 | *.pdb
23 | *.pgc
24 | *.pgd
25 | *.rsp
26 | *.sbr
27 | *.tlb
28 | *.tli
29 | *.tlh
30 | *.tmp
31 | *.vspscc
32 | .builds
33 | *.dotCover
34 |
35 | ## TODO: If you have NuGet Package Restore enabled, uncomment this
36 | #packages/
37 |
38 | # Visual C++ cache files
39 | ipch/
40 | *.aps
41 | *.ncb
42 | *.opensdf
43 | *.sdf
44 |
45 | # Visual Studio profiler
46 | *.psess
47 | *.vsp
48 |
49 | # ReSharper is a .NET coding add-in
50 | _ReSharper*
51 |
52 | # Installshield output folder
53 | [Ee]xpress
54 |
55 | # DocProject is a documentation generator add-in
56 | DocProject/buildhelp/
57 | DocProject/Help/*.HxT
58 | DocProject/Help/*.HxC
59 | DocProject/Help/*.hhc
60 | DocProject/Help/*.hhk
61 | DocProject/Help/*.hhp
62 | DocProject/Help/Html2
63 | DocProject/Help/html
64 |
65 | # Click-Once directory
66 | publish
67 |
68 | # Others
69 | [Oo]bj
70 | sql
71 | TestResults
72 | *.Cache
73 | ClientBin
74 | stylecop.*
75 | ~$*
76 | *.dbmdl
77 | Generated_Code #added for RIA/Silverlight projects
78 |
79 | # Backup & report files from converting an old project file to a newer
80 | # Visual Studio version. Backup files are not needed, because we have git ;-)
81 | _UpgradeReport_Files/
82 | Backup*/
83 | UpgradeLog*.XML
84 |
85 |
86 |
87 | ############
88 | ## Windows
89 | ############
90 |
91 | # Windows image file caches
92 | Thumbs.db
93 |
94 | # Folder config file
95 | Desktop.ini
96 |
97 | # Mac crap
98 | .DS_Store
99 |
--------------------------------------------------------------------------------
/CTP.Brokers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 4040
9 |
10 | tcp://yhzx-front1.yhqh.com:51205
11 | tcp://yhzx-front3.yhqh.com:52205
12 | tcp://101.95.8.178:53205
13 |
14 |
15 | tcp://yhzx-front1.yhqh.com:41213
16 | tcp://yhzx-front3.yhqh.com:41213
17 | tcp://101.95.8.178:53213
18 |
19 |
20 |
21 |
22 |
23 | 4040
24 |
25 | tcp://yhzx-front2.yhqh.com:51205
26 | tcp://yhzx-front4.yhqh.com:52205
27 | tcp://58.247.171.146:53205
28 |
29 |
30 | tcp://yhzx-front2.yhqh.com:41213
31 | tcp://yhzx-front4.yhqh.com:41213
32 | tcp://58.247.171.146:53213
33 |
34 |
35 |
36 |
37 |
38 | 4040
39 |
40 | tcp://yhctp-front1.yhqh.com:41205
41 | tcp://yhctp-front3.yhqh.com:41205
42 |
43 |
44 | tcp://yhctp-front1.yhqh.com:41213
45 | tcp://yhctp-front3.yhqh.com:41213
46 |
47 |
48 |
49 |
50 |
51 | 4040
52 |
53 | tcp://yhctp-front2.yhqh.com:41205
54 | tcp://yhctp-front4.yhqh.com:41205
55 |
56 |
57 | tcp://yhctp-front2.yhqh.com:41213
58 | tcp://yhctp-front4.yhqh.com:41213
59 |
60 |
61 |
62 |
63 |
64 | 4040
65 |
66 | tcp://192.168.106.51:41219
67 | tcp://192.168.106.52:41205
68 |
69 |
70 | tcp://192.168.106.51:41207
71 | tcp://192.168.106.52:41213
72 |
73 |
74 |
75 |
76 | 3030
77 |
78 | tcp://124.207.185.168:4120
79 |
80 |
81 | tcp://124.207.185.168:4121
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | 1013
93 |
94 | tcp://218.1.96.8:41205
95 |
96 |
97 | tcp://218.1.96.8:41213
98 |
99 |
100 |
101 |
102 |
103 | 4000
104 |
105 | tcp://203.110.179.220:41205
106 |
107 |
108 | tcp://203.110.179.220:41213
109 |
110 |
111 |
112 |
113 |
114 | 4000
115 |
116 | tcp://211.144.195.157:41205
117 |
118 |
119 | tcp://211.144.195.157:41213
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | 1002
131 |
132 | tcp://sim-front1.ctp.shcifco.com:31205
133 | tcp://sim-front2.ctp.shcifco.com:31205
134 |
135 |
136 | tcp://sim-md1.ctp.shcifco.com:31213
137 | tcp://sim-md2.ctp.shcifco.com:31213
138 |
139 |
140 |
141 |
142 |
143 | 8070
144 |
145 | tcp://zjzx-front1.ctp.shcifco.com:41205
146 | tcp://zjzx-front2.ctp.shcifco.com:41205
147 | tcp://zjzx-front3.ctp.shcifco.com:41205
148 | tcp://zjzx-front4.ctp.shcifco.com:41205
149 | tcp://zjzx-front5.ctp.shcifco.com:41205
150 |
151 |
152 | tcp://zjzx-md1.ctp.shcifco.com:41213
153 | tcp://zjzx-md2.ctp.shcifco.com:41213
154 | tcp://zjzx-md3.ctp.shcifco.com:41213
155 | tcp://zjzx-md4.ctp.shcifco.com:41213
156 | tcp://zjzx-md5.ctp.shcifco.com:41213
157 |
158 |
159 |
160 |
161 |
162 | 8070
163 |
164 | tcp://zjzx-front11.ctp.shcifco.com:41205
165 | tcp://zjzx-front12.ctp.shcifco.com:41205
166 | tcp://zjzx-front13.ctp.shcifco.com:41205
167 | tcp://zjzx-front14.ctp.shcifco.com:41205
168 | tcp://zjzx-front15.ctp.shcifco.com:41205
169 |
170 |
171 | tcp://zjzx-md11.ctp.shcifco.com:41213
172 | tcp://zjzx-md12.ctp.shcifco.com:41213
173 | tcp://zjzx-md13.ctp.shcifco.com:41213
174 | tcp://zjzx-md14.ctp.shcifco.com:41213
175 | tcp://zjzx-md15.ctp.shcifco.com:41213
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 | 1001
187 |
188 | tcp://180.168.102.230:26205
189 |
190 |
191 | tcp://180.168.102.230:26213
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 | 1017
203 |
204 | tcp://ctpmn1-front1.citicsf.com:51205
205 | tcp://ctpmn1-front2.citicsf.com:51205
206 |
207 |
208 | tcp://ctpmn1-front1.citicsf.com:51213
209 | tcp://ctpmn1-front2.citicsf.com:51213
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 | 8090
221 |
222 | tcp://58.246.40.180:26205
223 |
224 |
225 | tcp://58.246.40.180:26213
226 |
227 |
228 |
229 |
230 |
231 | 8090
232 |
233 | tcp://cifco-front1.financial-trading-platform.com:41205
234 | tcp://cifco-front3.financial-trading-platform.com:41205
235 | tcp://cifco-front4.financial-trading-platform.com:41205
236 | tcp://cifco-front5.financial-trading-platform.com:41205
237 | tcp://cifco-front7.financial-trading-platform.com:41205
238 | tcp://cifco-front8.financial-trading-platform.com:41205
239 | tcp://cifco-front9.financial-trading-platform.com:41205
240 |
241 |
242 | tcp://cifco-md1.financial-trading-platform.com:41213
243 | tcp://cifco-md3.financial-trading-platform.com:41213
244 | tcp://cifco-md4.financial-trading-platform.com:41213
245 | tcp://cifco-md5.financial-trading-platform.com:41213
246 | tcp://cifco-md7.financial-trading-platform.com:41213
247 | tcp://cifco-md8.financial-trading-platform.com:41213
248 | tcp://cifco-md9.financial-trading-platform.com:41213
249 |
250 |
251 |
252 |
253 |
254 | 8090
255 |
256 | tcp://cifco-front2.financial-trading-platform.com:41205
257 | tcp://cifco-front6.financial-trading-platform.com:41205
258 | tcp://cifco-front9.financial-trading-platform.com:41205
259 |
260 |
261 | tcp://cifco-md2.financial-trading-platform.com:41213
262 | tcp://cifco-md6.financial-trading-platform.com:41213
263 | tcp://cifco-md9.financial-trading-platform.com:41213
264 |
265 |
266 |
267 |
268 |
269 | 8090
270 |
271 | tcp://218.241.197.56:41205
272 | tcp://218.241.197.55:41205
273 |
274 |
275 | tcp://218.241.197.56:41213
276 | tcp://218.241.197.55:41213
277 |
278 |
279 |
280 |
281 |
282 | 8090
283 |
284 | tcp://123.127.45.138:41205
285 | tcp://123.127.45.137:41205
286 | tcp://123.127.45.139:41205
287 |
288 |
289 | tcp://123.127.45.138:41213
290 | tcp://123.127.45.137:41213
291 | tcp://123.127.45.139:41213
292 |
293 |
294 |
295 |
296 |
297 | 8090
298 |
299 | tcp://61.144.241.113:41205
300 | tcp://61.144.241.114:41205
301 | tcp://61.144.241.115:41205
302 |
303 |
304 | tcp://61.144.241.113:41213
305 | tcp://61.144.241.114:41213
306 | tcp://61.144.241.115:41213
307 |
308 |
309 |
310 |
311 |
312 | 8090
313 |
314 | tcp://210.22.25.180:41205
315 | tcp://210.22.25.184:41205
316 |
317 |
318 | tcp://210.22.25.180:41213
319 | tcp://210.22.25.184:41213
320 |
321 |
322 |
323 |
324 |
325 | 8090
326 |
327 | tcp://218.241.197.52:41205
328 | tcp://218.241.197.53:41205
329 | tcp://218.241.197.54:41205
330 | tcp://123.127.45.145:41205
331 | tcp://218.241.197.59:41205
332 |
333 |
334 | tcp://218.241.197.52:41213
335 | tcp://218.241.197.53:41213
336 | tcp://218.241.197.54:41213
337 | tcp://123.127.45.145:41213
338 | tcp://218.241.197.59:41213
339 |
340 |
341 |
342 |
343 |
344 | 8090
345 |
346 | tcp://123.127.45.141:41205
347 | tcp://123.127.45.144:41205
348 | tcp://123.127.45.142:41205
349 | tcp://123.127.45.143:41205
350 | tcp://123.127.45.145:41205
351 |
352 |
353 | tcp://123.127.45.141:41213
354 | tcp://123.127.45.144:41213
355 | tcp://123.127.45.142:41213
356 | tcp://123.127.45.143:41213
357 | tcp://123.127.45.145:41213
358 |
359 |
360 |
361 |
362 |
363 |
364 |
--------------------------------------------------------------------------------
/CTPZQ.Brokers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 2011
9 |
10 | tcp://116.228.234.67:41205
11 |
12 |
13 | tcp://116.228.234.67:41213
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/OpenQuant-CTP/31e0187e912fdb1baa56e52d9d87e50f57ffb049/LICENSE.txt
--------------------------------------------------------------------------------
/QuantBox.nlog:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenQuant内盘期货插件
2 |
3 | ## 目的
4 | 将OpenQuant与国内的CTP进行对接,让OpenQuant直接能交易国内期货
5 |
6 | ## 设计思路
7 | 1. 利用了本开源项目的C-CTP接口,与CSharp-CTP接口
8 | 2. C-CTP、CSharp-CTP都以dll方式调用
9 | 3. 本插件同时支持QuantDeveloper、OpenQuant2和OpenQuant3(以下分别简称QD、OQ2和OQ3),只要进行再编译即可
10 | 4. 为了支持查询合约列表功能,不使用OpenQuant接口,而是使用更底层的SmartQuant接口
11 |
12 | ## 如何安装使用
13 | 1. 找到SmartQuant接口插件目录C:\Program Files\SmartQuant Ltd\OpenQuant\Framework\bin\
14 | 2. 复制QuantBox.OQ.CTP.dll这个SQ插件,确保此插件的版本正确
15 | 3. 找到OpenQuant接口插件目录C:\Program Files\SmartQuant Ltd\OpenQuant\Bin\
16 | 4. 复制thostmduserapi.dll、thosttraderapi.dll两个CTP的dll到此目录
17 | 5. 复制QuantBox.C2CTP.dll、QuantBox.CSharp2CTP.dll、QuantBox.Helper.CTP.dll、NLog.dll到此目录
18 | 6. 复制CTP.nlog到此目录,或自己修改此文件
19 | 7. 找到软件的插件配置文件C:\Documents and Settings\Administrator\Application Data\SmartQuant Ltd\OpenQuant\Framework\ini\framework.xml
20 | 8. 添加``到对应位置
21 | 9. 如何使用请查看插件的使用说明
22 |
23 | ## 如何开发
24 | 1. 确保你的C-CTP接口的dll、CSharp-CTP接口等都是最新的
25 | 3. 修改引用中有关SmartQuant类库的地址,使用你目标OQ中下的dll
26 | 4. 修改.NET框架要使用的版本,QD使用2.0,OQ2使用3.5,OQ3使用4.0
27 | 5. 修改dll生成的目录,具体请参考如何安装。
28 | 6. 调试只能使用附加到进程,建议学习并使用远程调试
29 | 7. 如果插件完全无法加载,请找到对应的log文件,查看日志。
30 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/CTPAPI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using QuantBox.OQ.Extensions;
4 | using SmartQuant.FIX;
5 |
6 | #if CTP
7 | using QuantBox.CSharp2CTP;
8 |
9 | namespace QuantBox.Helper.CTP
10 | #elif CTPZQ
11 | using QuantBox.CSharp2CTPZQ;
12 |
13 | namespace QuantBox.Helper.CTPZQ
14 | #endif
15 | {
16 | public sealed class CTPAPI
17 | {
18 | private static readonly CTPAPI instance = new CTPAPI();
19 | private CTPAPI()
20 | {
21 | }
22 | public static CTPAPI GetInstance()
23 | {
24 | return instance;
25 | }
26 |
27 |
28 | private IntPtr m_pMdApi = IntPtr.Zero; //行情对象指针
29 | private IntPtr m_pTdApi = IntPtr.Zero; //交易对象指针
30 |
31 | public void __RegTdApi(IntPtr pTdApi)
32 | {
33 | m_pTdApi = pTdApi;
34 | }
35 |
36 | public void __RegMdApi(IntPtr pMdApi)
37 | {
38 | m_pMdApi = pMdApi;
39 | }
40 |
41 | #region 合列列表
42 | public Dictionary Instruments { get; private set; }
43 | public void __RegInstrumentDictionary(Dictionary dict)
44 | {
45 | Instruments = dict;
46 | }
47 |
48 | public delegate void RspQryInstrument(CThostFtdcInstrumentField pInstrument);
49 | public event RspQryInstrument OnRspQryInstrument;
50 | public void FireOnRspQryInstrument(CThostFtdcInstrumentField pInstrument)
51 | {
52 | if (null != OnRspQryInstrument)
53 | {
54 | OnRspQryInstrument(pInstrument);
55 | }
56 | }
57 |
58 | public void ReqQryInstrument(string instrument)
59 | {
60 | if (null != Instruments)
61 | {
62 | CThostFtdcInstrumentField value;
63 | if (Instruments.TryGetValue(instrument, out value))
64 | {
65 | FireOnRspQryInstrument(value);
66 | return;
67 | }
68 | }
69 |
70 | if (!string.IsNullOrEmpty(instrument)
71 | && null != m_pTdApi
72 | && IntPtr.Zero != m_pTdApi)
73 | {
74 | TraderApi.TD_ReqQryInstrument(m_pTdApi, instrument);
75 | }
76 | }
77 | #endregion
78 |
79 | #region 保证金率
80 | #if CTP
81 | public Dictionary MarginRates { get; private set; }
82 | public void __RegInstrumentMarginRateDictionary(Dictionary dict)
83 | {
84 | MarginRates = dict;
85 | }
86 | public void ReqQryInstrumentMarginRate(string instrument, TThostFtdcHedgeFlagType HedgeFlag)
87 | {
88 | if (null != MarginRates)
89 | {
90 | CThostFtdcInstrumentMarginRateField value;
91 | if (MarginRates.TryGetValue(instrument, out value))
92 | {
93 | FireOnRspQryInstrumentMarginRate(value);
94 | return;
95 | }
96 | }
97 |
98 | if (!string.IsNullOrEmpty(instrument)
99 | && null != m_pTdApi
100 | && IntPtr.Zero != m_pTdApi)
101 | {
102 | TraderApi.TD_ReqQryInstrumentMarginRate(m_pTdApi, instrument, HedgeFlag);
103 | }
104 | }
105 |
106 | public delegate void RspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateField pInstrumentMarginRate);
107 | public event RspQryInstrumentMarginRate OnRspQryInstrumentMarginRate;
108 | public void FireOnRspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateField pInstrumentMarginRate)
109 | {
110 | if (null != OnRspQryInstrumentMarginRate)
111 | {
112 | OnRspQryInstrumentMarginRate(pInstrumentMarginRate);
113 | }
114 | }
115 | #endif
116 | #endregion
117 |
118 | #region 手续费率
119 | public Dictionary CommissionRates { get; private set; }
120 | public void __RegInstrumentCommissionRateDictionary(Dictionary dict)
121 | {
122 | CommissionRates = dict;
123 | }
124 |
125 | public void ReqQryInstrumentCommissionRate(string instrument)
126 | {
127 | if (null != CommissionRates)
128 | {
129 | CThostFtdcInstrumentCommissionRateField value;
130 | if (CommissionRates.TryGetValue(instrument, out value))
131 | {
132 | FireOnRspQryInstrumentCommissionRate(value);
133 | return;
134 | }
135 | }
136 |
137 | if (!string.IsNullOrEmpty(instrument)
138 | && null != m_pTdApi
139 | && IntPtr.Zero != m_pTdApi)
140 | {
141 | TraderApi.TD_ReqQryInstrumentCommissionRate(m_pTdApi, instrument);
142 | }
143 | }
144 |
145 | public delegate void RspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateField pInstrumentCommissionRate);
146 | public event RspQryInstrumentCommissionRate OnRspQryInstrumentCommissionRate;
147 | public void FireOnRspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateField pInstrumentCommissionRate)
148 | {
149 | if (null != OnRspQryInstrumentCommissionRate)
150 | {
151 | OnRspQryInstrumentCommissionRate(pInstrumentCommissionRate);
152 | }
153 | }
154 | #endregion
155 |
156 | #region 深度行情1
157 | public Dictionary DepthMarketDatas { get; private set; }
158 | public void __RegDepthMarketDataDictionary(Dictionary dict)
159 | {
160 | DepthMarketDatas = dict;
161 | }
162 |
163 | public void ReqQryDepthMarketData(string instrument)
164 | {
165 | if (null != DepthMarketDatas)
166 | {
167 | CThostFtdcDepthMarketDataField value;
168 | if (DepthMarketDatas.TryGetValue(instrument, out value))
169 | {
170 | FireOnRspQryDepthMarketData(value);
171 | return;
172 | }
173 | }
174 |
175 | if (!string.IsNullOrEmpty(instrument)
176 | && null != m_pTdApi
177 | && IntPtr.Zero != m_pTdApi)
178 | {
179 | TraderApi.TD_ReqQryDepthMarketData(m_pTdApi, instrument);
180 | }
181 | }
182 |
183 | public delegate void RspQryDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData);
184 | public event RspQryDepthMarketData OnRspQryDepthMarketData;
185 | public void FireOnRspQryDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData)
186 | {
187 | if (null != OnRspQryDepthMarketData)
188 | {
189 | OnRspQryDepthMarketData(pDepthMarketData);
190 | }
191 | }
192 | #endregion
193 |
194 | #region 交易所状态
195 | public delegate void RtnInstrumentStatus(CThostFtdcInstrumentStatusField pInstrumentStatus);
196 | public event RtnInstrumentStatus OnRtnInstrumentStatus;
197 | public void FireOnRtnInstrumentStatus(CThostFtdcInstrumentStatusField pInstrumentStatus)
198 | {
199 | if (null != OnRtnInstrumentStatus)
200 | {
201 | OnRtnInstrumentStatus(pInstrumentStatus);
202 | }
203 | }
204 | #endregion
205 |
206 | #region 主动请求资金
207 | public CThostFtdcTradingAccountField TradingAccount { get; private set; }
208 | public void __RegTradingAccount(CThostFtdcTradingAccountField pTradingAccount)
209 | {
210 | TradingAccount = pTradingAccount;
211 | }
212 |
213 | public void ReqQryTradingAccount()
214 | {
215 | if (m_pTdApi == null || m_pTdApi == IntPtr.Zero)
216 | return;
217 |
218 | TraderApi.TD_ReqQryTradingAccount(m_pTdApi);
219 | }
220 |
221 | public delegate void RspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount);
222 | public event RspQryTradingAccount OnRspQryTradingAccount;
223 | public void FireOnRspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount)
224 | {
225 | if (null != OnRspQryTradingAccount)
226 | {
227 | OnRspQryTradingAccount(pTradingAccount);
228 | }
229 | }
230 | #endregion
231 |
232 | #region 主动查持仓
233 | public Dictionary InvestorPositions { get; private set; }
234 | public void __RegInvestorPositionDictionary(Dictionary dict)
235 | {
236 | InvestorPositions = dict;
237 | }
238 | public void ReqQryInvestorPosition(string instrument)
239 | {
240 | if (null != m_pTdApi
241 | && IntPtr.Zero != m_pTdApi)
242 | {
243 | TraderApi.TD_ReqQryInvestorPosition(m_pTdApi, instrument);
244 | }
245 | }
246 |
247 | public delegate void RspReqQryInvestorPosition(CThostFtdcInvestorPositionField pInvestorPosition);
248 | public event RspReqQryInvestorPosition OnRspReqQryInvestorPosition;
249 | public void FireOnRspReqQryInvestorPosition(CThostFtdcInvestorPositionField pInvestorPosition)
250 | {
251 | if (null != OnRspReqQryInvestorPosition)
252 | {
253 | OnRspReqQryInvestorPosition(pInvestorPosition);
254 | }
255 | }
256 | #endregion
257 |
258 | #region 询价
259 | public delegate void RtnForQuoteRsp(CThostFtdcForQuoteRspField pForQuoteRsp);
260 | public event RtnForQuoteRsp OnRtnForQuoteRsp;
261 | public void FireOnRtnForQuoteRsp(CThostFtdcForQuoteRspField pForQuoteRsp)
262 | {
263 | if (null != OnRtnForQuoteRsp)
264 | {
265 | OnRtnForQuoteRsp(pForQuoteRsp);
266 | }
267 | }
268 | #endregion
269 |
270 | #region OnStrategyStart
271 | public EventHandler OnLive;
272 | public void EmitOnLive()
273 | {
274 | if (OnLive != null)
275 | OnLive(null, EventArgs.Empty);
276 | }
277 | #endregion
278 |
279 | #region 错误类型转换
280 | public static EnumError FromCTP(int ErrorID)
281 | {
282 | ErrorType e = (ErrorType)ErrorID;
283 |
284 | switch (e)
285 | {
286 | case ErrorType.NONE:
287 | return EnumError.SUCCESS;
288 | case ErrorType.INSUFFICIENT_MONEY:
289 | return EnumError.INSUFFICIENT_MONEY;
290 | case ErrorType.OVER_CLOSE_POSITION:
291 | return EnumError.OVER_CLOSE_POSITION;
292 | case ErrorType.OVER_CLOSETODAY_POSITION:
293 | return EnumError.OVER_CLOSETODAY_POSITION;
294 | case ErrorType.OVER_CLOSEYESTERDAY_POSITION:
295 | return EnumError.OVER_CLOSEYESTERDAY_POSITION;
296 | default:
297 | return EnumError.OTHER;
298 | }
299 | }
300 | #endregion
301 |
302 | #region 开平转换
303 | public static TThostFtdcOffsetFlagType ToCTP(EnumOpenClose offset)
304 | {
305 | switch (offset)
306 | {
307 | case EnumOpenClose.OPEN:
308 | return TThostFtdcOffsetFlagType.Open;
309 | case EnumOpenClose.CLOSE:
310 | return TThostFtdcOffsetFlagType.Close;
311 | case EnumOpenClose.CLOSE_TODAY:
312 | return TThostFtdcOffsetFlagType.CloseToday;
313 | default:
314 | return TThostFtdcOffsetFlagType.Open;
315 | }
316 | }
317 | #endregion
318 |
319 | #region 买卖转换
320 | public static Side FromCTP(TThostFtdcDirectionType Direction)
321 | {
322 | switch (Direction)
323 | {
324 | case TThostFtdcDirectionType.Buy:
325 | return Side.Buy;
326 | case TThostFtdcDirectionType.Sell:
327 | return Side.Sell;
328 | default:
329 | return Side.Undefined;
330 | }
331 | }
332 | #endregion
333 | }
334 | }
335 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/CTPQuote.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using SmartQuant.Data;
4 |
5 | #if CTP
6 | using QuantBox.CSharp2CTP;
7 |
8 | namespace QuantBox.Helper.CTP
9 | #elif CTPZQ
10 | using QuantBox.CSharp2CTPZQ;
11 |
12 | namespace QuantBox.Helper.CTPZQ
13 | #endif
14 | {
15 | public class CTPQuote:Quote
16 | {
17 | public CTPQuote():base()
18 | {
19 | }
20 |
21 | public CTPQuote(Quote quote): base(quote)
22 | {
23 | }
24 |
25 | public CTPQuote(DateTime datetime, double bid, int bidSize, double ask, int askSize)
26 | : base(datetime, bid, bidSize, ask, askSize)
27 | {
28 | }
29 |
30 | public CThostFtdcDepthMarketDataField DepthMarketData;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/CTPTrade.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using SmartQuant.Data;
4 |
5 |
6 | #if CTP
7 | using QuantBox.CSharp2CTP;
8 |
9 | namespace QuantBox.Helper.CTP
10 | #elif CTPZQ
11 | using QuantBox.CSharp2CTPZQ;
12 |
13 | namespace QuantBox.Helper.CTPZQ
14 | #endif
15 | {
16 | public class CTPTrade:Trade
17 | {
18 | public CTPTrade():base()
19 | {
20 | }
21 |
22 | public CTPTrade(Trade trade):base(trade)
23 | {
24 | }
25 |
26 | public CTPTrade(DateTime datetime, double price, int size)
27 | : base(datetime, price, size)
28 | {
29 | }
30 |
31 | public CThostFtdcDepthMarketDataField DepthMarketData;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/DataConvert.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | #if OQ
4 | using OpenQuant.API;
5 | #elif QD
6 | using SmartQuant.Data;
7 | #endif
8 |
9 | #if CTP
10 | using QuantBox.CSharp2CTP;
11 |
12 | namespace QuantBox.Helper.CTP
13 | #elif CTPZQ
14 | using QuantBox.CSharp2CTPZQ;
15 |
16 | namespace QuantBox.Helper.CTPZQ
17 | #endif
18 | {
19 | public class DataConvert
20 | {
21 | static FieldInfo tradeField;
22 | static FieldInfo quoteField;
23 |
24 | public static bool TryConvert(Trade trade, ref CThostFtdcDepthMarketDataField DepthMarketData)
25 | {
26 | #if OQ
27 | if (tradeField == null)
28 | {
29 | tradeField = typeof(Trade).GetField("trade", BindingFlags.NonPublic | BindingFlags.Instance);
30 | }
31 |
32 | CTPTrade t = tradeField.GetValue(trade) as CTPTrade;
33 | #elif QD
34 | CTPTrade t = trade as CTPTrade;
35 | #endif
36 | if (null != t)
37 | {
38 | DepthMarketData = t.DepthMarketData;
39 | return true;
40 | }
41 |
42 | return false;
43 | }
44 |
45 | public static bool TryConvert(Quote quote, ref CThostFtdcDepthMarketDataField DepthMarketData)
46 | {
47 | #if OQ
48 | if (quoteField == null)
49 | {
50 | quoteField = typeof(Quote).GetField("quote", BindingFlags.NonPublic | BindingFlags.Instance);
51 | }
52 |
53 | CTPQuote q = quoteField.GetValue(quote) as CTPQuote;
54 | #elif QD
55 | CTPQuote q = quote as CTPQuote;
56 | #endif
57 | if (null != q)
58 | {
59 | DepthMarketData = q.DepthMarketData;
60 | return true;
61 | }
62 | return false;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的常规信息通过以下
6 | // 特性集控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("QuantBox.Helper.CTP")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("QuantBox.cn")]
12 | [assembly: AssemblyProduct("QuantBox.Helper.CTP")]
13 | [assembly: AssemblyCopyright("Copyright © QuantBox.cn 2012")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 使此程序集中的类型
18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
19 | // 则将该类型上的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("39f42680-fb9b-4dce-9497-b68ca230b2fb")]
24 |
25 | // 程序集的版本信息由下面四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 内部版本号
30 | // 修订号
31 | //
32 | // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.1.6.3")]
36 | [assembly: AssemblyFileVersion("1.1.6.3")]
37 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/QuantBox.Helper.CTP.Net35.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {2C5C5377-E34C-4515-9404-3461AAE70A8A}
9 | Library
10 | Properties
11 | QuantBox.Helper.CTP
12 | QuantBox.Helper.CTP
13 | v3.5
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\QuantDeveloper .NET\bin\
22 | TRACE;DEBUG;CTP,QD
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | ..\..\bin\
30 | TRACE;CTP,QD
31 | prompt
32 | 4
33 |
34 |
35 |
36 | False
37 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\QuantDeveloper .NET\bin\QuantBox.CSharp2CTP.dll
38 |
39 |
40 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll
41 |
42 |
43 | False
44 | ..\..\..\..\Program Files (x86)\SmartQuant Ltd\QuantDeveloper .NET\bin\SmartQuant.Data.dll
45 |
46 |
47 | False
48 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.FIX.dll
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
71 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/QuantBox.Helper.CTP.Net40.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {97AE93EC-5897-43C8-8D84-D92B73FE1434}
9 | Library
10 | Properties
11 | QuantBox.Helper.CTP
12 | QuantBox.Helper.CTP
13 | v4.0
14 | 512
15 |
16 |
17 | true
18 | full
19 | false
20 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Bin\
21 | TRACE;DEBUG;CTP,OQ
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | ..\..\bin\
29 | TRACE;CTP,OQ
30 | prompt
31 | 4
32 |
33 |
34 |
35 | False
36 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\Newtonsoft.Json.dll
37 |
38 |
39 | False
40 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\OpenQuant.API.dll
41 |
42 |
43 | False
44 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTP.dll
45 |
46 |
47 | False
48 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll
49 |
50 |
51 | False
52 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Data.dll
53 |
54 |
55 | False
56 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.FIX.dll
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
79 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/QuantBox.Helper.CTPZQ.Net35.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {4A6B6C0F-D169-4358-B42F-FAE8743DE897}
9 | Library
10 | Properties
11 | QuantBox.Helper.CTPZQ
12 | QuantBox.Helper.CTPZQ
13 | v3.5
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Bin\
22 | TRACE;DEBUG;CTPZQ,QD
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | ..\..\bin\
30 | TRACE;CTPZQ,QD
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTPZQ.dll
37 |
38 |
39 | False
40 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll
41 |
42 |
43 | False
44 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Data.dll
45 |
46 |
47 | False
48 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.FIX.dll
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
71 |
--------------------------------------------------------------------------------
/src/QuantBox.Helper.CTP/QuantBox.Helper.CTPZQ.Net40.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {5CAEB588-BA0F-4313-8B78-5101E97D695A}
9 | Library
10 | Properties
11 | QuantBox.Helper.CTPZQ
12 | QuantBox.Helper.CTPZQ
13 | v4.0
14 | 512
15 |
16 |
17 | true
18 | full
19 | false
20 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Bin\
21 | TRACE;DEBUG;CTPZQ,OQ
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | ..\..\bin\
29 | TRACE;CTPZQ,OQ
30 | prompt
31 | 4
32 |
33 |
34 |
35 | False
36 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\OpenQuant.API.dll
37 |
38 |
39 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTPZQ.dll
40 |
41 |
42 | False
43 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll
44 |
45 |
46 | False
47 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Data.dll
48 |
49 |
50 | False
51 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.FIX.dll
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
74 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantBox.Helper.CTP.Net40", "QuantBox.Helper.CTP\QuantBox.Helper.CTP.Net40.csproj", "{97AE93EC-5897-43C8-8D84-D92B73FE1434}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantBox.OQ.CTP.OQ3", "QuantBox.OQ.CTP\QuantBox.OQ.CTP.OQ3.csproj", "{72BE4BFC-E0F6-436F-8206-C6009932D620}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantBox.Helper.CTPZQ.Net40", "QuantBox.Helper.CTP\QuantBox.Helper.CTPZQ.Net40.csproj", "{5CAEB588-BA0F-4313-8B78-5101E97D695A}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantBox.OQ.CTPZQ.OQ3", "QuantBox.OQ.CTP\QuantBox.OQ.CTPZQ.OQ3.csproj", "{49F99E4A-F8D0-4CB8-84B2-39B4F6AC3576}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {97AE93EC-5897-43C8-8D84-D92B73FE1434}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {97AE93EC-5897-43C8-8D84-D92B73FE1434}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {97AE93EC-5897-43C8-8D84-D92B73FE1434}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {97AE93EC-5897-43C8-8D84-D92B73FE1434}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {72BE4BFC-E0F6-436F-8206-C6009932D620}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {72BE4BFC-E0F6-436F-8206-C6009932D620}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {72BE4BFC-E0F6-436F-8206-C6009932D620}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {72BE4BFC-E0F6-436F-8206-C6009932D620}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {5CAEB588-BA0F-4313-8B78-5101E97D695A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {5CAEB588-BA0F-4313-8B78-5101E97D695A}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {5CAEB588-BA0F-4313-8B78-5101E97D695A}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {5CAEB588-BA0F-4313-8B78-5101E97D695A}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {49F99E4A-F8D0-4CB8-84B2-39B4F6AC3576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {49F99E4A-F8D0-4CB8-84B2-39B4F6AC3576}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {49F99E4A-F8D0-4CB8-84B2-39B4F6AC3576}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {49F99E4A-F8D0-4CB8-84B2-39B4F6AC3576}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.CTP.MarketData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SmartQuant;
3 | using SmartQuant.Data;
4 | using SmartQuant.Instruments;
5 | using QuantBox.OQ.CTP;
6 |
7 | #if CTP
8 | using QuantBox.CSharp2CTP;
9 | using QuantBox.Helper.CTP;
10 |
11 | namespace QuantBox.OQ.CTP
12 | #elif CTPZQ
13 | using QuantBox.CSharp2CTPZQ;
14 | using QuantBox.Helper.CTPZQ;
15 |
16 | namespace QuantBox.OQ.CTPZQ
17 | #endif
18 | {
19 | partial class APIProvider
20 | {
21 | #region 深度行情回调
22 | private DateTime _dateTime = DateTime.Now;
23 | private void OnRtnDepthMarketData(IntPtr pApi, ref CThostFtdcDepthMarketDataField pDepthMarketData)
24 | {
25 | #if CTP
26 | string symbol = pDepthMarketData.InstrumentID;
27 | #elif CTPZQ
28 | string symbol = GetYahooSymbol(pDepthMarketData.InstrumentID, pDepthMarketData.ExchangeID);
29 | #endif
30 | DataRecord record;
31 | if (!_dictAltSymbol2Instrument.TryGetValue(symbol, out record))
32 | {
33 | mdlog.Warn("合约{0}不在订阅列表中却收到了数据", symbol);
34 | return;
35 | }
36 |
37 | Instrument instrument = record.Instrument;
38 |
39 | CThostFtdcDepthMarketDataField DepthMarket;
40 | _dictDepthMarketData.TryGetValue(symbol, out DepthMarket);
41 |
42 | //将更新字典的功能提前,因为如果一开始就OnTrade中下单,涨跌停没有更新
43 | _dictDepthMarketData[symbol] = pDepthMarketData;
44 |
45 | if (TimeMode.LocalTime == _TimeMode)
46 | {
47 | //为了生成正确的Bar,使用本地时间
48 | _dateTime = Clock.Now;
49 | }
50 | else
51 | {
52 | //直接按HH:mm:ss来解析,测试过这种方法目前是效率比较高的方法
53 | try
54 | {
55 | // 只有使用交易所行情时才需要处理跨天的问题
56 | #if CTP
57 | ChangeActionDay(pDepthMarketData.ActionDay);
58 | #else
59 | ChangeActionDay(pDepthMarketData.TradingDay);
60 | #endif
61 |
62 | int HH = int.Parse(pDepthMarketData.UpdateTime.Substring(0, 2));
63 | int mm = int.Parse(pDepthMarketData.UpdateTime.Substring(3, 2));
64 | int ss = int.Parse(pDepthMarketData.UpdateTime.Substring(6, 2));
65 |
66 | _dateTime = new DateTime(_yyyy, _MM, _dd, HH, mm, ss, pDepthMarketData.UpdateMillisec);
67 | }
68 | catch (Exception)
69 | {
70 | _dateTime = Clock.Now;
71 | }
72 | }
73 |
74 | if (record.TradeRequested)
75 | {
76 | //通过测试,发现IB的Trade与Quote在行情过来时数量是不同的,在这也做到不同
77 | if (DepthMarket.LastPrice == pDepthMarketData.LastPrice
78 | && DepthMarket.Volume == pDepthMarketData.Volume)
79 | { }
80 | else
81 | {
82 | //行情过来时是今天累计成交量,得转换成每个tick中成交量之差
83 | int volume = pDepthMarketData.Volume - DepthMarket.Volume;
84 | if (0 == DepthMarket.Volume)
85 | {
86 | //没有接收到最开始的一条,所以这计算每个Bar的数据时肯定超大,强行设置为0
87 | volume = 0;
88 | }
89 | else if (volume < 0)
90 | {
91 | //如果隔夜运行,会出现今早成交量0-昨收盘成交量,出现负数,所以当发现为负时要修改
92 | volume = pDepthMarketData.Volume;
93 | }
94 |
95 | // 使用新的类,保存更多信息
96 | CTPTrade trade = new CTPTrade(_dateTime,
97 | pDepthMarketData.LastPrice == double.MaxValue ? 0 : pDepthMarketData.LastPrice,
98 | volume);
99 |
100 | // 记录深度数据
101 | trade.DepthMarketData = pDepthMarketData;
102 |
103 | EmitNewTradeEvent(instrument, trade);
104 | }
105 | }
106 |
107 | if (record.QuoteRequested)
108 | {
109 | //if (
110 | //DepthMarket.BidVolume1 == pDepthMarketData.BidVolume1
111 | //&& DepthMarket.AskVolume1 == pDepthMarketData.AskVolume1
112 | //&& DepthMarket.BidPrice1 == pDepthMarketData.BidPrice1
113 | //&& DepthMarket.AskPrice1 == pDepthMarketData.AskPrice1
114 | //)
115 | //{ }
116 | //else
117 | {
118 | CTPQuote quote = new CTPQuote(_dateTime,
119 | pDepthMarketData.BidPrice1 == double.MaxValue ? 0 : pDepthMarketData.BidPrice1,
120 | pDepthMarketData.BidVolume1,
121 | pDepthMarketData.AskPrice1 == double.MaxValue ? 0 : pDepthMarketData.AskPrice1,
122 | pDepthMarketData.AskVolume1
123 | );
124 |
125 | quote.DepthMarketData = pDepthMarketData;
126 |
127 | EmitNewQuoteEvent(instrument, quote);
128 | }
129 | }
130 |
131 | if (record.MarketDepthRequested)
132 | {
133 | bool bAsk = true;
134 | bool bBid = true;
135 |
136 | if (bAsk)
137 | bAsk = EmitNewMarketDepth(instrument, _dateTime, 0, MDSide.Ask, pDepthMarketData.AskPrice1, pDepthMarketData.AskVolume1);
138 | if (bBid)
139 | bBid = EmitNewMarketDepth(instrument, _dateTime, 0, MDSide.Bid, pDepthMarketData.BidPrice1, pDepthMarketData.BidVolume1);
140 | #if CTPZQ
141 | if(bAsk)
142 | bAsk = EmitNewMarketDepth(instrument, _dateTime, 1, MDSide.Ask, pDepthMarketData.AskPrice2, pDepthMarketData.AskVolume2);
143 | if(bBid)
144 | bBid = EmitNewMarketDepth(instrument, _dateTime, 1, MDSide.Bid, pDepthMarketData.BidPrice2, pDepthMarketData.BidVolume2);
145 |
146 | if(bAsk)
147 | bAsk = EmitNewMarketDepth(instrument, _dateTime, 2, MDSide.Ask, pDepthMarketData.AskPrice3, pDepthMarketData.AskVolume3);
148 | if(bBid)
149 | bBid = EmitNewMarketDepth(instrument, _dateTime, 2, MDSide.Bid, pDepthMarketData.BidPrice3, pDepthMarketData.BidVolume3);
150 |
151 | if(bAsk)
152 | bAsk = EmitNewMarketDepth(instrument, _dateTime, 3, MDSide.Ask, pDepthMarketData.AskPrice4, pDepthMarketData.AskVolume4);
153 | if(bBid)
154 | bBid = EmitNewMarketDepth(instrument, _dateTime, 3, MDSide.Bid, pDepthMarketData.BidPrice4, pDepthMarketData.BidVolume4);
155 |
156 | if(bAsk)
157 | bAsk = EmitNewMarketDepth(instrument, _dateTime, 4, MDSide.Ask, pDepthMarketData.AskPrice5, pDepthMarketData.AskVolume5);
158 | if(bBid)
159 | bBid = EmitNewMarketDepth(instrument, _dateTime, 4, MDSide.Bid, pDepthMarketData.BidPrice5, pDepthMarketData.BidVolume5);
160 | #endif
161 | }
162 | }
163 |
164 | public void OnRspQryDepthMarketData(IntPtr pTraderApi, ref CThostFtdcDepthMarketDataField pDepthMarketData, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
165 | {
166 | if (0 == pRspInfo.ErrorID)
167 | {
168 | CThostFtdcDepthMarketDataField DepthMarket;
169 | if (!_dictDepthMarketData.TryGetValue(pDepthMarketData.InstrumentID, out DepthMarket))
170 | {
171 | //没找到此元素,保存一下
172 | _dictDepthMarketData[pDepthMarketData.InstrumentID] = pDepthMarketData;
173 | }
174 |
175 | tdlog.Info("已经接收查询深度行情 {0}", pDepthMarketData.InstrumentID);
176 | //通知单例
177 | CTPAPI.GetInstance().FireOnRspQryDepthMarketData(pDepthMarketData);
178 | }
179 | else
180 | {
181 | tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryDepthMarketData:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
182 | EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryDepthMarketData:" + pRspInfo.ErrorMsg);
183 | }
184 | }
185 | #endregion
186 |
187 |
188 |
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.CTP.Quote.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using SmartQuant.Execution;
5 | using SmartQuant.FIX;
6 | using SmartQuant.Instruments;
7 | using Newtonsoft.Json;
8 | using QuantBox.OQ.Extensions;
9 | using QuantBox.OQ.Extensions.OrderText;
10 | using QuantBox.OQ.Extensions.Combiner;
11 | using QuantBox.OQ.Extensions.OrderItem;
12 |
13 | #if CTP
14 | using QuantBox.CSharp2CTP;
15 | using QuantBox.Helper.CTP;
16 |
17 | namespace QuantBox.OQ.CTP
18 | #elif CTPZQ
19 | using QuantBox.CSharp2CTPZQ;
20 | using QuantBox.Helper.CTPZQ;
21 |
22 | namespace QuantBox.OQ.CTPZQ
23 | #endif
24 | {
25 | partial class APIProvider
26 | {
27 | #region 询价
28 | private void OnRtnForQuoteRsp(IntPtr pMdUserApi, ref CThostFtdcForQuoteRspField pForQuoteRsp)
29 | {
30 | Console.WriteLine("OnRtnForQuoteRsp");
31 | // 询价请求
32 | CTPAPI.GetInstance().FireOnRtnForQuoteRsp(pForQuoteRsp);
33 | }
34 | #endregion
35 |
36 | private void OnErrRtnQuoteAction(IntPtr pTraderApi, ref CThostFtdcQuoteActionField pQuoteAction, ref CThostFtdcRspInfoField pRspInfo)
37 | {
38 | Console.WriteLine("OnErrRtnQuoteAction");
39 | }
40 |
41 | private void OnErrRtnQuoteInsert(IntPtr pTraderApi, ref CThostFtdcInputQuoteField pInputQuote, ref CThostFtdcRspInfoField pRspInfo)
42 | {
43 | Console.WriteLine("OnErrRtnQuoteAction");
44 | }
45 |
46 | private void OnRspQuoteAction(IntPtr pTraderApi, ref CThostFtdcInputQuoteActionField pInputQuoteAction, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
47 | {
48 | Console.WriteLine("OnRspQuoteAction");
49 | }
50 |
51 | private void OnRspQuoteInsert(IntPtr pTraderApi, ref CThostFtdcInputQuoteField pInputQuote, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
52 | {
53 | Console.WriteLine("OnRspQuoteInsert");
54 | }
55 |
56 | private void OnRtnQuote(IntPtr pTraderApi, ref CThostFtdcQuoteField pQuote)
57 | {
58 | Console.WriteLine("OnRtnQuote");
59 | }
60 |
61 |
62 | #region 发双向报价单
63 | private void Send(QuoteOrderItem item)
64 | {
65 | if (item == null)
66 | return;
67 |
68 | SingleOrder AskOrder = item.Sell.Order;
69 | SingleOrder BidOrder = item.Buy.Order;
70 |
71 | string symbol = item.Buy.Order.Symbol;
72 |
73 | double AskPrice = AskOrder.Price;
74 | double BidPrice = BidOrder.Price;
75 | int AskVolume = (int)AskOrder.OrderQty;
76 | int BidVolume = (int)BidOrder.OrderQty;
77 |
78 | TThostFtdcOffsetFlagType AskOffsetFlag = CTPAPI.ToCTP(item.Sell.OpenClose);
79 | TThostFtdcOffsetFlagType BidOffsetFlag = CTPAPI.ToCTP(item.Buy.OpenClose);
80 |
81 | TThostFtdcHedgeFlagType AskHedgeFlag = HedgeFlagType;
82 | TThostFtdcHedgeFlagType BidHedgeFlag = HedgeFlagType;
83 |
84 | int nRet = 0;
85 | #if CTP
86 | nRet = TraderApi.TD_SendQuote(m_pTdApi,
87 | -1,
88 | symbol,
89 | AskPrice,
90 | BidPrice,
91 | AskVolume,
92 | BidVolume,
93 | AskOffsetFlag,
94 | BidOffsetFlag,
95 | AskHedgeFlag,
96 | BidHedgeFlag);
97 | #endif
98 | if (nRet > 0)
99 | {
100 | orderMap.CreateNewOrder(string.Format("{0}:{1}:{2}", _RspUserLogin.FrontID, _RspUserLogin.SessionID, nRet), item);
101 | }
102 | }
103 | #endregion
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.CTP.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Windows.Forms;
7 | using SmartQuant;
8 | using SmartQuant.Data;
9 | using SmartQuant.Execution;
10 | using SmartQuant.FIX;
11 | using SmartQuant.Instruments;
12 | using SmartQuant.Providers;
13 | using QuantBox.OQ.CTP;
14 |
15 | using QuantBox.OQ.Extensions.Combiner;
16 | using QuantBox.OQ.Extensions.OrderItem;
17 |
18 | #if CTP
19 | using QuantBox.CSharp2CTP;
20 | using QuantBox.Helper.CTP;
21 |
22 | namespace QuantBox.OQ.CTP
23 | #elif CTPZQ
24 | using QuantBox.CSharp2CTPZQ;
25 | using QuantBox.Helper.CTPZQ;
26 |
27 | namespace QuantBox.OQ.CTPZQ
28 | #endif
29 | {
30 | partial class APIProvider
31 | {
32 | private fnOnConnect _fnOnConnect_Holder;
33 | private fnOnDisconnect _fnOnDisconnect_Holder;
34 | private fnOnErrRtnOrderAction _fnOnErrRtnOrderAction_Holder;
35 | private fnOnErrRtnOrderInsert _fnOnErrRtnOrderInsert_Holder;
36 | private fnOnRspError _fnOnRspError_Holder;
37 | private fnOnRspOrderAction _fnOnRspOrderAction_Holder;
38 | private fnOnRspOrderInsert _fnOnRspOrderInsert_Holder;
39 | private fnOnRspQryDepthMarketData _fnOnRspQryDepthMarketData_Holder;
40 | private fnOnRspQryInstrument _fnOnRspQryInstrument_Holder;
41 | private fnOnRspQryInstrumentCommissionRate _fnOnRspQryInstrumentCommissionRate_Holder;
42 | private fnOnRspQryInvestorPosition _fnOnRspQryInvestorPosition_Holder;
43 | private fnOnRspQryTradingAccount _fnOnRspQryTradingAccount_Holder;
44 | private fnOnRtnDepthMarketData _fnOnRtnDepthMarketData_Holder;
45 | private fnOnRtnForQuoteRsp _fnOnRtnForQuoteRsp_Holder;
46 | private fnOnRtnInstrumentStatus _fnOnRtnInstrumentStatus_Holder;
47 | private fnOnRtnOrder _fnOnRtnOrder_Holder;
48 | private fnOnRtnTrade _fnOnRtnTrade_Holder;
49 |
50 | #if CTP
51 | private fnOnRspQryInstrumentMarginRate _fnOnRspQryInstrumentMarginRate_Holder;
52 | #endif
53 | private fnOnErrRtnQuoteAction _fnOnErrRtnQuoteAction_Holder;
54 | private fnOnErrRtnQuoteInsert _fnOnErrRtnQuoteInsert_Holder;
55 | private fnOnRspQuoteAction _fnOnRspQuoteAction_Holder;
56 | private fnOnRspQuoteInsert _fnOnRspQuoteInsert_Holder;
57 | private fnOnRtnQuote _fnOnRtnQuote_Holder;
58 |
59 | #region 回调
60 | private void InitCallbacks()
61 | {
62 | //由于回调函数可能被GC回收,所以用成员变量将回调函数保存下来
63 | _fnOnConnect_Holder = OnConnect;
64 | _fnOnDisconnect_Holder = OnDisconnect;
65 | _fnOnErrRtnOrderAction_Holder = OnErrRtnOrderAction;
66 | _fnOnErrRtnOrderInsert_Holder = OnErrRtnOrderInsert;
67 | _fnOnRspError_Holder = OnRspError;
68 | _fnOnRspOrderAction_Holder = OnRspOrderAction;
69 | _fnOnRspOrderInsert_Holder = OnRspOrderInsert;
70 | _fnOnRspQryDepthMarketData_Holder = OnRspQryDepthMarketData;
71 | _fnOnRspQryInstrument_Holder = OnRspQryInstrument;
72 | _fnOnRspQryInstrumentCommissionRate_Holder = OnRspQryInstrumentCommissionRate;
73 | _fnOnRspQryInvestorPosition_Holder = OnRspQryInvestorPosition;
74 | _fnOnRspQryTradingAccount_Holder = OnRspQryTradingAccount;
75 | _fnOnRtnInstrumentStatus_Holder = OnRtnInstrumentStatus;
76 | _fnOnRtnDepthMarketData_Holder = OnRtnDepthMarketData;
77 | _fnOnRtnOrder_Holder = OnRtnOrder;
78 | _fnOnRtnTrade_Holder = OnRtnTrade;
79 |
80 | #if CTP
81 | _fnOnRspQryInstrumentMarginRate_Holder = OnRspQryInstrumentMarginRate;
82 | #endif
83 |
84 | _fnOnRtnForQuoteRsp_Holder = OnRtnForQuoteRsp;
85 | _fnOnErrRtnQuoteAction_Holder = OnErrRtnQuoteAction;
86 | _fnOnErrRtnQuoteInsert_Holder = OnErrRtnQuoteInsert;
87 | _fnOnRspQuoteAction_Holder = OnRspQuoteAction;
88 | _fnOnRspQuoteInsert_Holder = OnRspQuoteInsert;
89 | _fnOnRtnQuote_Holder = OnRtnQuote;
90 | }
91 | #endregion
92 |
93 | private IntPtr m_pMsgQueue = IntPtr.Zero; //消息队列指针
94 | private IntPtr m_pMdApi = IntPtr.Zero; //行情对象指针
95 | private IntPtr m_pTdApi = IntPtr.Zero; //交易对象指针
96 |
97 | //行情有效状态,约定连接上并通过认证为有效
98 | private volatile bool _bMdConnected;
99 | //交易有效状态,约定连接上,通过认证并进行结算单确认为有效
100 | private volatile bool _bTdConnected;
101 |
102 | //表示用户操作,也许有需求是用户有多个行情,只连接第一个等
103 | private bool _bWantMdConnect;
104 | private bool _bWantTdConnect;
105 |
106 | private readonly object _lockMd = new object();
107 | private readonly object _lockTd = new object();
108 | private readonly object _lockMsgQueue = new object();
109 |
110 | //记录交易登录成功后的SessionID、FrontID等信息
111 | private CThostFtdcRspUserLoginField _RspUserLogin;
112 |
113 | // 报单信息维护
114 | private readonly OrderMap orderMap = new OrderMap();
115 |
116 | //记录账号的实际持仓,保证以最低成本选择开平
117 | private readonly Dictionary _dictPositions = new Dictionary();
118 | //记录合约实际行情,用于向界面通知行情用,这里应当记录AltSymbol
119 | private readonly Dictionary _dictDepthMarketData = new Dictionary();
120 | //记录合约列表,从实盘合约名到对象的映射
121 | private readonly Dictionary _dictInstruments = new Dictionary();
122 | private Dictionary _dictInstruments2 = new Dictionary();
123 | //记录手续费率,从实盘合约名到对象的映射
124 | private readonly Dictionary _dictCommissionRate = new Dictionary();
125 | //记录保证金率,从实盘合约名到对象的映射
126 | private readonly Dictionary _dictMarginRate = new Dictionary();
127 | //记录
128 | private readonly Dictionary _dictAltSymbol2Instrument = new Dictionary();
129 |
130 | //用于行情的时间,只在登录时改动,所以要求开盘时能得到更新
131 | private int _yyyy;
132 | private int _MM;
133 | private int _dd;
134 |
135 | private ServerItem server;
136 | private AccountItem account;
137 |
138 | #region 合约列表
139 | private void OnRspQryInstrument(IntPtr pTraderApi, ref CThostFtdcInstrumentField pInstrument, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
140 | {
141 | if (0 == pRspInfo.ErrorID)
142 | {
143 | #if CTP
144 | _dictInstruments[pInstrument.InstrumentID] = pInstrument;
145 | #else
146 | //比较无语,测试平台上会显示很多无效数据,有关期货的还会把正确的数据给覆盖,所以临时这样处理
147 | if (pInstrument.ProductClass != TThostFtdcProductClassType.Futures)
148 | {
149 | string symbol = GetYahooSymbol(pInstrument.InstrumentID, pInstrument.ExchangeID);
150 | _dictInstruments[symbol] = pInstrument;
151 |
152 | // 行情中可能没有交易所信息,这个容器用于容错处理
153 | _dictInstruments2[pInstrument.InstrumentID] = symbol;
154 | }
155 | #endif
156 |
157 | if (bIsLast)
158 | {
159 | tdlog.Info("合约列表已经接收完成,共{0}条", _dictInstruments.Count);
160 | }
161 | }
162 | else
163 | {
164 | tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryInstrument:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
165 | EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryInstrument:" + pRspInfo.ErrorMsg);
166 | }
167 | }
168 | #endregion
169 |
170 | #region 手续费列表
171 | private void OnRspQryInstrumentCommissionRate(IntPtr pTraderApi, ref CThostFtdcInstrumentCommissionRateField pInstrumentCommissionRate, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
172 | {
173 | if (0 == pRspInfo.ErrorID)
174 | {
175 | _dictCommissionRate[pInstrumentCommissionRate.InstrumentID] = pInstrumentCommissionRate;
176 | tdlog.Info("已经接收手续费率 {0}", pInstrumentCommissionRate.InstrumentID);
177 |
178 | //通知单例
179 | CTPAPI.GetInstance().FireOnRspQryInstrumentCommissionRate(pInstrumentCommissionRate);
180 | }
181 | else
182 | {
183 | tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryInstrumentCommissionRate:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
184 | EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryInstrumentCommissionRate:" + pRspInfo.ErrorMsg);
185 | }
186 | }
187 | #endregion
188 |
189 | #region 保证金率列表
190 | #if CTP
191 | private void OnRspQryInstrumentMarginRate(IntPtr pTraderApi, ref CThostFtdcInstrumentMarginRateField pInstrumentMarginRate, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
192 | {
193 | if (0 == pRspInfo.ErrorID)
194 | {
195 | _dictMarginRate[pInstrumentMarginRate.InstrumentID] = pInstrumentMarginRate;
196 | tdlog.Info("已经接收保证金率 {0}", pInstrumentMarginRate.InstrumentID);
197 |
198 | //通知单例
199 | CTPAPI.GetInstance().FireOnRspQryInstrumentMarginRate(pInstrumentMarginRate);
200 | }
201 | else
202 | {
203 | tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryInstrumentMarginRate:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
204 | EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryInstrumentMarginRate:" + pRspInfo.ErrorMsg);
205 | }
206 | }
207 | #endif
208 | #endregion
209 |
210 | #region 持仓回报
211 | private string GetPositionKey(string InstrumentID,
212 | TThostFtdcPosiDirectionType PosiDirection,
213 | TThostFtdcHedgeFlagType HedgeFlag,
214 | TThostFtdcPositionDateType PositionDate)
215 | {
216 | return string.Format("{0}:{1}:{2}:{3}", InstrumentID, PosiDirection, HedgeFlag, PositionDate);
217 | }
218 |
219 | private string GetPositionKey(CThostFtdcInvestorPositionField p)
220 | {
221 | return GetPositionKey(p.InstrumentID, p.PosiDirection, p.HedgeFlag, p.PositionDate);
222 | }
223 |
224 | private void OnRspQryInvestorPosition(IntPtr pTraderApi, ref CThostFtdcInvestorPositionField pInvestorPosition, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
225 | {
226 | if (0 == pRspInfo.ErrorID)
227 | {
228 | string key = GetPositionKey(pInvestorPosition);
229 | _dictPositions[key] = pInvestorPosition;
230 | CTPAPI.GetInstance().FireOnRspReqQryInvestorPosition(pInvestorPosition);
231 |
232 | timerPonstion.Enabled = false;
233 | timerPonstion.Enabled = true;
234 | }
235 | else
236 | {
237 | tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryInvestorPosition:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
238 | EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryInvestorPosition:" + pRspInfo.ErrorMsg);
239 | }
240 | }
241 | #endregion
242 |
243 | #region 资金回报
244 | CThostFtdcTradingAccountField m_TradingAccount;
245 | private void OnRspQryTradingAccount(IntPtr pTraderApi, ref CThostFtdcTradingAccountField pTradingAccount, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLastt)
246 | {
247 | if (0 == pRspInfo.ErrorID)
248 | {
249 | m_TradingAccount = pTradingAccount;
250 |
251 | //有资金信息过来了,重新计时
252 | timerAccount.Enabled = false;
253 | timerAccount.Enabled = true;
254 |
255 | //通知单例,还是使用GetBrokerInfo来取呢?
256 | CTPAPI.GetInstance().__RegTradingAccount(m_TradingAccount);
257 | CTPAPI.GetInstance().FireOnRspQryTradingAccount(pTradingAccount);
258 | }
259 | else
260 | {
261 | tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryTradingAccount:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
262 | EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryTradingAccount:" + pRspInfo.ErrorMsg);
263 | }
264 | }
265 | #endregion
266 |
267 | #region 错误回调
268 | private void OnRspError(IntPtr pApi, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast)
269 | {
270 | tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspError:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
271 | EmitError(nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg);
272 | }
273 | #endregion
274 |
275 | #region 交易所状态
276 | private void OnRtnInstrumentStatus(IntPtr pTraderApi, ref CThostFtdcInstrumentStatusField pInstrumentStatus)
277 | {
278 | tdlog.Info("{0},{1},{2},{3},{4},{5},{6},{7}",
279 | pInstrumentStatus.ExchangeID, pInstrumentStatus.InstrumentID,
280 | pInstrumentStatus.InstrumentStatus, pInstrumentStatus.EnterReason,
281 | pInstrumentStatus.EnterTime,pInstrumentStatus.TradingSegmentSN,
282 | pInstrumentStatus.ExchangeInstID,pInstrumentStatus.SettlementGroupID);
283 |
284 | //通知单例
285 | CTPAPI.GetInstance().FireOnRtnInstrumentStatus(pInstrumentStatus);
286 |
287 | // 到IF的交割日,是否会收到两个有关IF的记录?如果在此进行清理是否会有问题?
288 | // 只会收到一条
289 | // 遍历是否过期
290 | if (pInstrumentStatus.InstrumentStatus == TThostFtdcInstrumentStatusType.Closed)
291 | {
292 | Dictionary tmp = new Dictionary();
293 | foreach (var pair in orderMap.OrderItem_OrderField)
294 | {
295 | if(pair.Value.ExchangeID == pInstrumentStatus.ExchangeID)
296 | {
297 | int cnt = pair.Key.GetLegNum();
298 | foreach(var pair2 in orderMap.Order_OrderItem)
299 | {
300 | // 得找到OpenQuant层的单子
301 | if(pair.Key == pair2.Value)
302 | {
303 | --cnt;
304 | EmitExpired(pair2.Key);
305 | if (cnt <= 0)
306 | break;
307 | }
308 | }
309 | tmp[pair.Key] = pair.Value;
310 | }
311 | }
312 |
313 | foreach (var pair in tmp)
314 | {
315 | OnLastStatus(pair.Key, pair.Value.OrderSysID, pair.Value.OrderRef);
316 | }
317 | tmp.Clear();
318 | }
319 | }
320 | #endregion
321 | }
322 | }
323 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.ExecutionProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using SmartQuant;
5 | using SmartQuant.Execution;
6 | using SmartQuant.FIX;
7 | using SmartQuant.Providers;
8 | using System.Reflection;
9 | using QuantBox.OQ.CTP;
10 |
11 | #if CTP
12 | using QuantBox.CSharp2CTP;
13 | using QuantBox.Helper.CTP;
14 |
15 | namespace QuantBox.OQ.CTP
16 | #elif CTPZQ
17 | using QuantBox.CSharp2CTPZQ;
18 | using QuantBox.Helper.CTPZQ;
19 |
20 | namespace QuantBox.OQ.CTPZQ
21 | #endif
22 | {
23 | public partial class APIProvider : IExecutionProvider
24 | {
25 | private readonly Dictionary orderRecords = new Dictionary();
26 |
27 | public event ExecutionReportEventHandler ExecutionReport;
28 | public event OrderCancelRejectEventHandler OrderCancelReject;
29 |
30 | public BrokerInfo GetBrokerInfo()
31 | {
32 | BrokerInfo brokerInfo = new BrokerInfo();
33 |
34 | if (IsConnected)
35 | {
36 | if (!_bTdConnected || string.IsNullOrEmpty(m_TradingAccount.AccountID))
37 | {
38 | return brokerInfo;
39 | }
40 |
41 | BrokerAccount brokerAccount = new BrokerAccount(m_TradingAccount.AccountID) { BuyingPower = m_TradingAccount.Available };
42 |
43 | Type t = typeof(CThostFtdcTradingAccountField);
44 | FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance);
45 | foreach (FieldInfo field in fields)
46 | {
47 | brokerAccount.AddField(field.Name, field.GetValue(m_TradingAccount).ToString());
48 | }
49 |
50 | foreach (CThostFtdcInvestorPositionField pos in _dictPositions.Values)
51 | {
52 | BrokerPosition brokerPosition = new BrokerPosition
53 | {
54 | Symbol = pos.InstrumentID
55 | };
56 |
57 | if (TThostFtdcPosiDirectionType.Long == pos.PosiDirection)
58 | {
59 | brokerPosition.LongQty = pos.Position;
60 | }
61 | else if (TThostFtdcPosiDirectionType.Short == pos.PosiDirection)
62 | {
63 | brokerPosition.ShortQty = pos.Position;
64 | }
65 |
66 | brokerPosition.Qty = brokerPosition.LongQty - brokerPosition.ShortQty;
67 |
68 | Type t2 = typeof(CThostFtdcInvestorPositionField);
69 | FieldInfo[] fields2 = t2.GetFields(BindingFlags.Public | BindingFlags.Instance);
70 | foreach (FieldInfo field in fields2)
71 | {
72 | brokerPosition.AddCustomField(field.Name, field.GetValue(pos).ToString());
73 | }
74 | brokerAccount.AddPosition(brokerPosition);
75 | }
76 | brokerInfo.Accounts.Add(brokerAccount);
77 | }
78 |
79 | return brokerInfo;
80 | }
81 |
82 | public void SendNewOrderSingle(NewOrderSingle order)
83 | {
84 | SingleOrder key = order as SingleOrder;
85 | orderRecords.Add(key, new OrderRecord(key));
86 | Send(key);
87 | }
88 |
89 | #region QuantDeveloper下的接口
90 | public void SendOrderCancelReplaceRequest(FIXOrderCancelReplaceRequest request)
91 | {
92 | //IOrder order = OrderManager.Orders.All[request.OrigClOrdID];
93 | //SingleOrder order2 = order as SingleOrder;
94 | //this.provider.CallReplace(order2);
95 | EmitError(-1,-1,"不支持改单指令");
96 | tdlog.Error("不支持改单指令");
97 | }
98 |
99 | public void SendOrderCancelRequest(FIXOrderCancelRequest request)
100 | {
101 | IOrder order = OrderManager.Orders.All[request.OrigClOrdID];
102 | SingleOrder order2 = order as SingleOrder;
103 | Cancel(order2);
104 | }
105 |
106 | public void SendOrderStatusRequest(FIXOrderStatusRequest request)
107 | {
108 | throw new NotImplementedException();
109 | }
110 | #endregion
111 |
112 | private void EmitExecutionReport(ExecutionReport report)
113 | {
114 | if (ExecutionReport != null)
115 | {
116 | ExecutionReport(this, new ExecutionReportEventArgs(report));
117 | }
118 | }
119 |
120 | private void EmitOrderCancelReject(OrderCancelReject reject)
121 | {
122 | if (OrderCancelReject != null)
123 | {
124 | OrderCancelReject(this, new OrderCancelRejectEventArgs(reject));
125 | }
126 | }
127 |
128 | public void EmitExecutionReport(SingleOrder order, OrdStatus status)
129 | {
130 | EmitExecutionReport(order, status, "");
131 | }
132 |
133 | public void EmitExecutionReport(SingleOrder order, OrdStatus status, string text)
134 | {
135 | OrderRecord record = orderRecords[order];
136 | EmitExecutionReport(record, status, 0.0, 0, text, CommType.Absolute, 0);
137 | }
138 |
139 | public void EmitExecutionReport(SingleOrder order, double price, int quantity)
140 | {
141 | OrderRecord record = orderRecords[order];
142 | EmitExecutionReport(record, OrdStatus.Undefined, price, quantity, "", CommType.Absolute, 0);
143 | }
144 |
145 | public void EmitExecutionReport(SingleOrder order, double price, int quantity, CommType commType, double commission)
146 | {
147 | OrderRecord record = orderRecords[order];
148 | EmitExecutionReport(record, OrdStatus.Undefined, price, quantity, "", commType, commission);
149 | }
150 |
151 | private void EmitExecutionReport(OrderRecord record, OrdStatus ordStatus, double lastPx, int lastQty, string text, CommType commType, double commission)
152 | {
153 | ExecutionReport report = new ExecutionReport
154 | {
155 | TransactTime = Clock.Now,
156 | ClOrdID = record.Order.ClOrdID,
157 | OrigClOrdID = record.Order.ClOrdID,
158 | OrderID = record.Order.OrderID,
159 | Symbol = record.Order.Symbol,
160 | SecurityType = record.Order.SecurityType,
161 | SecurityExchange = record.Order.SecurityExchange,
162 | Currency = record.Order.Currency,
163 | CommType = commType,
164 | Commission = commission,
165 | Side = record.Order.Side,
166 |
167 | OrdType = record.Order.OrdType,
168 | TimeInForce = record.Order.TimeInForce,
169 | OrderQty = record.Order.OrderQty,
170 | Price = record.Order.Price,
171 | StopPx = record.Order.StopPx,
172 | LastPx = lastPx,
173 | LastQty = lastQty
174 | };
175 |
176 | if (ordStatus == OrdStatus.Replaced)
177 | {
178 | report.OrdType = record.Order.ReplaceOrder.ContainsField(EFIXField.OrdType) ? record.Order.ReplaceOrder.OrdType : record.Order.OrdType;
179 | report.TimeInForce = record.Order.ReplaceOrder.ContainsField(EFIXField.TimeInForce) ? record.Order.ReplaceOrder.TimeInForce : record.Order.TimeInForce;
180 | report.OrderQty = record.Order.ReplaceOrder.ContainsField(EFIXField.OrderQty) ? record.Order.ReplaceOrder.OrderQty : record.Order.OrderQty;
181 | report.Price = record.Order.ReplaceOrder.ContainsField(EFIXField.Price) ? record.Order.ReplaceOrder.Price : record.Order.Price;
182 | report.StopPx = record.Order.ReplaceOrder.ContainsField(EFIXField.StopPx) ? record.Order.ReplaceOrder.StopPx : record.Order.StopPx;
183 | record.LeavesQty = ((int)report.OrderQty) - record.CumQty;
184 | }
185 | else
186 | {
187 | report.OrdType = record.Order.OrdType;
188 | report.TimeInForce = record.Order.TimeInForce;
189 | report.OrderQty = record.Order.OrderQty;
190 | report.Price = record.Order.Price;
191 | report.StopPx = record.Order.StopPx;
192 | }
193 |
194 |
195 | if (ordStatus == OrdStatus.Undefined)
196 | {
197 | record.AddFill(lastPx, lastQty);
198 | if (record.LeavesQty > 0)
199 | {
200 | ordStatus = OrdStatus.PartiallyFilled;
201 | }
202 | else
203 | {
204 | ordStatus = OrdStatus.Filled;
205 | }
206 | }
207 | report.AvgPx = record.AvgPx;
208 | report.CumQty = record.CumQty;
209 | report.LeavesQty = record.LeavesQty;
210 | report.ExecType = GetExecType(ordStatus);
211 | report.OrdStatus = ordStatus;
212 | report.Text = text;
213 |
214 | EmitExecutionReport(report);
215 | }
216 |
217 | protected void EmitAccepted(SingleOrder order)
218 | {
219 | EmitExecutionReport(order, OrdStatus.New);
220 | }
221 |
222 | protected void EmitCancelled(SingleOrder order)
223 | {
224 | EmitExecutionReport(order, OrdStatus.Cancelled);
225 | }
226 |
227 | protected void EmitExpired(SingleOrder order)
228 | {
229 | EmitExecutionReport(order, OrdStatus.Expired);
230 | }
231 |
232 | protected void EmitPendingCancel(SingleOrder order)
233 | {
234 | EmitExecutionReport(order, OrdStatus.PendingCancel);
235 | }
236 |
237 | protected void EmitCancelReject(SingleOrder order, OrdStatus status, string message)
238 | {
239 | OrderCancelReject reject = new OrderCancelReject
240 | {
241 | TransactTime = Clock.Now,
242 | ClOrdID = order.ClOrdID,
243 | OrigClOrdID = order.ClOrdID,
244 | OrderID = order.OrderID,
245 |
246 | CxlRejReason = CxlRejReason.BrokerOption,
247 | CxlRejResponseTo = CxlRejResponseTo.CancelRequest,
248 | OrdStatus = status
249 | };
250 |
251 | EmitOrderCancelReject(reject);
252 | }
253 |
254 | protected void EmitFilled(SingleOrder order, double price, int quantity, CommType commType, double commission)
255 | {
256 | EmitExecutionReport(order, price, quantity,commType,commission);
257 | }
258 |
259 | protected void EmitRejected(SingleOrder order, string message)
260 | {
261 | EmitExecutionReport(order, OrdStatus.Rejected, message);
262 | }
263 |
264 | private static ExecType GetExecType(OrdStatus status)
265 | {
266 | switch (status)
267 | {
268 | case OrdStatus.New:
269 | return ExecType.New;
270 | case OrdStatus.PartiallyFilled:
271 | return ExecType.PartialFill;
272 | case OrdStatus.Filled:
273 | return ExecType.Fill;
274 | case OrdStatus.Cancelled:
275 | return ExecType.Cancelled;
276 | case OrdStatus.Replaced:
277 | return ExecType.Replace;
278 | case OrdStatus.PendingCancel:
279 | return ExecType.PendingCancel;
280 | case OrdStatus.Rejected:
281 | return ExecType.Rejected;
282 | case OrdStatus.PendingReplace:
283 | return ExecType.PendingReplace;
284 | case OrdStatus.Expired:
285 | return ExecType.Expired;
286 | }
287 | throw new ArgumentException(string.Format("Cannot find exec type for ord status - {0}", status));
288 | }
289 |
290 | #region OpenQuant3接口中的新方法
291 | public void RegisterOrder(NewOrderSingle order)
292 | {
293 | tdlog.Info("RegisterOrder");
294 | }
295 | #endregion
296 |
297 | #if OQ
298 | public void SendOrderCancelReplaceRequest(OrderCancelReplaceRequest request)
299 | {
300 | SendOrderCancelReplaceRequest(request as FIXOrderCancelReplaceRequest);
301 | }
302 |
303 | public void SendOrderCancelRequest(OrderCancelRequest request)
304 | {
305 | SendOrderCancelRequest(request as FIXOrderCancelRequest);
306 | }
307 |
308 | public void SendOrderStatusRequest(OrderStatusRequest request)
309 | {
310 | SendOrderStatusRequest(request as FIXOrderStatusRequest);
311 | }
312 | #endif
313 | }
314 | }
315 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.InstrumentProvider.cs:
--------------------------------------------------------------------------------
1 | using SmartQuant.FIX;
2 | using SmartQuant.Providers;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Globalization;
6 | using System.Text.RegularExpressions;
7 |
8 | #if CTP
9 | using QuantBox.CSharp2CTP;
10 | using QuantBox.Helper.CTP;
11 |
12 | namespace QuantBox.OQ.CTP
13 | #elif CTPZQ
14 | using QuantBox.CSharp2CTPZQ;
15 | using QuantBox.Helper.CTPZQ;
16 |
17 | namespace QuantBox.OQ.CTPZQ
18 | #endif
19 | {
20 | public partial class APIProvider : IInstrumentProvider
21 | {
22 | public event SecurityDefinitionEventHandler SecurityDefinition;
23 |
24 | public void SendSecurityDefinitionRequest(FIXSecurityDefinitionRequest request)
25 | {
26 | lock (this)
27 | {
28 | if (!_bTdConnected)
29 | {
30 | EmitError(-1, -1, "交易没有连接,无法获取合约列表");
31 | tdlog.Error("交易没有连接,无法获取合约列表");
32 | return;
33 | }
34 |
35 | string symbol = request.ContainsField(EFIXField.Symbol) ? request.Symbol : null;
36 | string securityType = request.ContainsField(EFIXField.SecurityType) ? request.SecurityType : null;
37 | string securityExchange = request.ContainsField(EFIXField.SecurityExchange) ? request.SecurityExchange : null;
38 |
39 | #region 过滤
40 | List list = new List();
41 | foreach (CThostFtdcInstrumentField inst in _dictInstruments.Values)
42 | {
43 | int flag = 0;
44 | if (null == symbol)
45 | {
46 | ++flag;
47 | }
48 | else if (inst.InstrumentID.ToUpper().StartsWith(symbol.ToUpper()))
49 | {
50 | ++flag;
51 | }
52 |
53 | if (null == securityExchange)
54 | {
55 | ++flag;
56 | }
57 | else if (inst.ExchangeID.ToUpper().StartsWith(securityExchange.ToUpper()))
58 | {
59 | ++flag;
60 | }
61 |
62 | if (null == securityType)
63 | {
64 | ++flag;
65 | }
66 | else
67 | {
68 | if (securityType == GetSecurityType(inst))
69 | {
70 | ++flag;
71 | }
72 | }
73 |
74 | if (3==flag)
75 | {
76 | list.Add(inst);
77 | }
78 | }
79 | #endregion
80 |
81 | list.Sort(SortCThostFtdcInstrumentField);
82 |
83 | //如果查出的数据为0,应当想法立即返回
84 | if (0==list.Count)
85 | {
86 | FIXSecurityDefinition definition = new FIXSecurityDefinition
87 | {
88 | SecurityReqID = request.SecurityReqID,
89 | SecurityResponseID = request.SecurityReqID,
90 | SecurityResponseType = request.SecurityRequestType,
91 | TotNoRelatedSym = 1//有个除0错误的问题
92 | };
93 | if (SecurityDefinition != null)
94 | {
95 | SecurityDefinition(this, new SecurityDefinitionEventArgs(definition));
96 | }
97 | }
98 |
99 | foreach (CThostFtdcInstrumentField inst in list)
100 | {
101 | FIXSecurityDefinition definition = new FIXSecurityDefinition
102 | {
103 | SecurityReqID = request.SecurityReqID,
104 | //SecurityResponseID = request.SecurityReqID,
105 | SecurityResponseType = request.SecurityRequestType,
106 | TotNoRelatedSym = list.Count
107 | };
108 |
109 | {
110 | string securityType2 = GetSecurityType(inst);
111 | definition.AddField(EFIXField.SecurityType, securityType2);
112 | }
113 | {
114 | double x = inst.PriceTick;
115 | if (x > 0.00001)
116 | {
117 | int i = 0;
118 | for (; x - (int)x != 0; ++i)
119 | {
120 | x = x * 10;
121 | }
122 | definition.AddField(EFIXField.PriceDisplay, string.Format("F{0}", i));
123 | definition.AddField(EFIXField.TickSize, inst.PriceTick);
124 | }
125 | }
126 | #if CTP
127 | definition.AddField(EFIXField.Symbol, inst.InstrumentID);
128 | #elif CTPZQ
129 | definition.AddField(EFIXField.Symbol, GetYahooSymbol(inst.InstrumentID, inst.ExchangeID));
130 | #endif
131 | definition.AddField(EFIXField.SecurityExchange, inst.ExchangeID);
132 | definition.AddField(EFIXField.Currency, "CNY");//Currency.CNY
133 | definition.AddField(EFIXField.SecurityDesc, inst.InstrumentName);
134 | definition.AddField(EFIXField.Factor, (double)inst.VolumeMultiple);
135 |
136 | if(inst.ProductClass == TThostFtdcProductClassType.Futures||inst.ProductClass == TThostFtdcProductClassType.Options)
137 | {
138 | try
139 | {
140 | definition.AddField(EFIXField.MaturityDate, DateTime.ParseExact(inst.ExpireDate, "yyyyMMdd", CultureInfo.InvariantCulture));
141 | }
142 | catch (Exception ex)
143 | {
144 | tdlog.Warn("合约:{0},字段内容:{1},{2}", inst.InstrumentID, inst.ExpireDate, ex.Message);
145 | }
146 |
147 | //if (inst.ProductClass == TThostFtdcProductClassType.Options)
148 | //{
149 | // // 支持中金所,大商所,郑商所
150 | // var match = Regex.Match(inst.InstrumentID, @"(\d+)(-?)([CP])(-?)(\d+)");
151 | // if (match.Success)
152 | // {
153 | // definition.AddField(EFIXField.PutOrCall, match.Groups[3].Value == "C" ? FIXPutOrCall.Call : FIXPutOrCall.Put);
154 | // definition.AddField(EFIXField.StrikePrice, double.Parse(match.Groups[5].Value));
155 | // }
156 | //}
157 | }
158 |
159 | // 中金所仿真平台下,居然全设的是股票
160 | var match = Regex.Match(inst.InstrumentID, @"(\d+)(-?)([CP])(-?)(\d+)");
161 | if (match.Success)
162 | {
163 | definition.AddField(EFIXField.PutOrCall, match.Groups[3].Value == "C" ? FIXPutOrCall.Call : FIXPutOrCall.Put);
164 | definition.AddField(EFIXField.StrikePrice, double.Parse(match.Groups[5].Value));
165 | }
166 |
167 | FIXSecurityAltIDGroup group = new FIXSecurityAltIDGroup();
168 | group.SecurityAltID = inst.InstrumentID;
169 | group.SecurityAltExchange = inst.ExchangeID;
170 | group.SecurityAltIDSource = this.Name;
171 |
172 | definition.AddGroup(group);
173 |
174 | //还得补全内容
175 |
176 | if (SecurityDefinition != null)
177 | {
178 | SecurityDefinition(this, new SecurityDefinitionEventArgs(definition));
179 | }
180 | }
181 | }
182 | }
183 |
184 | private static int SortCThostFtdcInstrumentField(CThostFtdcInstrumentField a1, CThostFtdcInstrumentField a2)
185 | {
186 | return a1.InstrumentID.CompareTo(a2.InstrumentID);
187 | }
188 | #region 证券接口
189 |
190 | /*
191 | * 上海证券交易所证券代码分配规则
192 | * http://www.docin.com/p-417422186.html
193 | *
194 | * http://wenku.baidu.com/view/f2e9ddf77c1cfad6195fa706.html
195 | */
196 | private string GetSecurityType(CThostFtdcInstrumentField inst)
197 | {
198 | string securityType = FIXSecurityType.CommonStock;
199 |
200 | try
201 | {
202 | switch (inst.ProductClass)
203 | {
204 | case TThostFtdcProductClassType.Futures:
205 | securityType = FIXSecurityType.Future;
206 | break;
207 | case TThostFtdcProductClassType.Combination:
208 | securityType = FIXSecurityType.MultiLegInstrument;//此处是否理解上有不同
209 | break;
210 | case TThostFtdcProductClassType.Options:
211 | securityType = FIXSecurityType.FutureOption;
212 | break;
213 | #if CTPZQ
214 | case TThostFtdcProductClassType.StockA:
215 | case TThostFtdcProductClassType.StockB:
216 | securityType = GetSecurityTypeStock(inst.ProductID, inst.InstrumentID);
217 | break;
218 | case TThostFtdcProductClassType.ETF:
219 | case TThostFtdcProductClassType.ETFPurRed:
220 | securityType = GetSecurityTypeETF(inst.ProductID, inst.InstrumentID);
221 | break;
222 | #endif
223 | default:
224 | securityType = FIXSecurityType.CommonStock;
225 | break;
226 | }
227 | return securityType;
228 | }
229 | catch(Exception ex)
230 | {
231 | tdlog.Warn("合约:{0},字段内容:{1}", inst.InstrumentID, ex.Message);
232 | }
233 |
234 | return securityType;
235 | }
236 |
237 | /*
238 | 从CTPZQ中遍历出来的所有ID
239 | GC 6 090002
240 | SHETF 8 500001
241 | SHA 6 600000
242 | SZA 6 000001
243 | SZBONDS 6 100213
244 | RC 6 131800
245 | SZETF 8 150001*/
246 | private string GetSecurityTypeStock(string ProductID, string InstrumentID)
247 | {
248 | string securityType = FIXSecurityType.CommonStock;
249 | switch (ProductID)
250 | {
251 | case "SHA":
252 | case "SZA":
253 | securityType = FIXSecurityType.CommonStock;
254 | break;
255 | case "SHBONDS":
256 | {
257 | int i = Convert.ToInt32(InstrumentID.Substring(0, 3));
258 | if (i == 0)
259 | {
260 | securityType = FIXSecurityType.Index;
261 | }
262 | else if (i < 700)
263 | {
264 | securityType = FIXSecurityType.USTreasuryBond;
265 | }
266 | else if (i < 800)
267 | {
268 | securityType = FIXSecurityType.CommonStock;
269 | }
270 | else
271 | {
272 | securityType = FIXSecurityType.USTreasuryBond;
273 | }
274 | }
275 | break;
276 | case "SZBONDS":
277 | {
278 | int i = Convert.ToInt32(InstrumentID.Substring(0, 2));
279 | if (i == 39)
280 | {
281 | securityType = FIXSecurityType.Index;
282 | }
283 | else
284 | {
285 | securityType = FIXSecurityType.USTreasuryBond;
286 | }
287 | }
288 | break;
289 | case "GC":
290 | case "RC":
291 | securityType = FIXSecurityType.USTreasuryBond;
292 | break;
293 | case "SHETF":
294 | case "SZETF":
295 | securityType = FIXSecurityType.ExchangeTradedFund;
296 | break;
297 | case "SHRATIONED":
298 | case "SZRATIONED":
299 | case "SZCYB":
300 | securityType = FIXSecurityType.CommonStock;
301 | break;
302 | default:
303 | securityType = FIXSecurityType.CommonStock;
304 | break;
305 | }
306 | return securityType;
307 | }
308 |
309 | private string GetSecurityTypeETF(string ProductID, string InstrumentID)
310 | {
311 | string securityType = FIXSecurityType.ExchangeTradedFund;
312 | switch (ProductID)
313 | {
314 | case "SHA":
315 | securityType = FIXSecurityType.CommonStock;
316 | break;
317 | case "SHETF":
318 | securityType = FIXSecurityType.ExchangeTradedFund;
319 | break;
320 | case "SZETF":
321 | securityType = FIXSecurityType.ExchangeTradedFund;
322 | break;
323 | case "SZA":
324 | {
325 | int i = Convert.ToInt32(InstrumentID.Substring(0, 2));
326 | if (i < 10)
327 | {
328 | securityType = FIXSecurityType.CommonStock;
329 | }
330 | else if (i < 15)
331 | {
332 | securityType = FIXSecurityType.USTreasuryBond;
333 | }
334 | else if (i < 20)
335 | {
336 | securityType = FIXSecurityType.ExchangeTradedFund;
337 | }
338 | else if (i < 30)
339 | {
340 | securityType = FIXSecurityType.CommonStock;
341 | }
342 | else if (i < 39)
343 | {
344 | securityType = FIXSecurityType.CommonStock;
345 | }
346 | else if (i == 39)
347 | {
348 | securityType = FIXSecurityType.Index;
349 | }
350 | else
351 | {
352 | securityType = FIXSecurityType.CommonStock;
353 | }
354 | }
355 | break;
356 | }
357 | return securityType;
358 | }
359 |
360 | private string GetYahooSymbol(string InstrumentID, string ExchangeID)
361 | {
362 | if (InstrumentID.Length >= 6 && ExchangeID.Length >= 2)
363 | {
364 | return string.Format("{0}.{1}", InstrumentID.Substring(0,6), ExchangeID.Substring(0, 2));
365 | }
366 | else
367 | {
368 | // 没有交易所信息时的容错处理
369 | string altSymbol;
370 | if (_dictInstruments2.TryGetValue(InstrumentID, out altSymbol))
371 | {
372 | return altSymbol;
373 | }
374 |
375 | return string.Format("{0}.{1}", InstrumentID, ExchangeID);
376 | }
377 | }
378 |
379 | private string GetApiSymbol(string Symbol)
380 | {
381 | var match = Regex.Match(Symbol, @"(\d+)\.(\w+)");
382 | if (match.Success)
383 | {
384 | var code = match.Groups[1].Value;
385 | return code;
386 | }
387 | return Symbol;
388 | }
389 |
390 | private string GetApiExchange(string Symbol)
391 | {
392 | var match = Regex.Match(Symbol, @"(\d+)\.(\w+)");
393 | if (match.Success)
394 | {
395 | var code = match.Groups[2].Value;
396 | return code;
397 | }
398 | return Symbol;
399 | }
400 | #endregion
401 | }
402 | }
403 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.MarketDataProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using SmartQuant.Data;
4 | using SmartQuant.FIX;
5 | using SmartQuant.Instruments;
6 | using SmartQuant.Providers;
7 | using QuantBox.OQ.CTP;
8 |
9 | #if CTP
10 | using QuantBox.CSharp2CTP;
11 | using QuantBox.Helper.CTP;
12 |
13 | namespace QuantBox.OQ.CTP
14 | #elif CTPZQ
15 | using QuantBox.CSharp2CTPZQ;
16 | using QuantBox.Helper.CTPZQ;
17 |
18 | namespace QuantBox.OQ.CTPZQ
19 | #endif
20 | {
21 | public partial class APIProvider:IMarketDataProvider
22 | {
23 | #if OQ
24 | public IMarketDataFilter MarketDataFilter { get; set; }
25 | #endif
26 | private IBarFactory factory;
27 |
28 | public event MarketDataRequestRejectEventHandler MarketDataRequestReject;
29 | public event MarketDataSnapshotEventHandler MarketDataSnapshot;
30 | public event BarEventHandler NewBar;
31 | public event BarEventHandler NewBarOpen;
32 | public event BarSliceEventHandler NewBarSlice;
33 | public event CorporateActionEventHandler NewCorporateAction;
34 | public event FundamentalEventHandler NewFundamental;
35 | public event BarEventHandler NewMarketBar;
36 | public event MarketDataEventHandler NewMarketData;
37 | public event MarketDepthEventHandler NewMarketDepth;
38 | public event QuoteEventHandler NewQuote;
39 | public event TradeEventHandler NewTrade;
40 |
41 | #region IMarketDataProvider
42 | [Category(CATEGORY_BARFACTORY)]
43 | public IBarFactory BarFactory
44 | {
45 | get
46 | {
47 | return factory;
48 | }
49 | set
50 | {
51 | if (factory != null)
52 | {
53 | factory.NewBar -= OnNewBar;
54 | factory.NewBarOpen -= OnNewBarOpen;
55 | factory.NewBarSlice -= OnNewBarSlice;
56 | }
57 | factory = value;
58 | if (factory != null)
59 | {
60 | factory.NewBar += OnNewBar;
61 | factory.NewBarOpen += OnNewBarOpen;
62 | factory.NewBarSlice += OnNewBarSlice;
63 | }
64 | }
65 | }
66 |
67 | private void OnNewBarSlice(object sender, BarSliceEventArgs args)
68 | {
69 | if (NewBarSlice != null)
70 | {
71 | NewBarSlice(this, new BarSliceEventArgs(args.BarSize, this));
72 | }
73 | }
74 |
75 | public void SendMarketDataRequest(FIXMarketDataRequest request)
76 | {
77 | if (!_bMdConnected)
78 | {
79 | EmitError(-1, -1, "行情服务器没有连接");
80 | mdlog.Error("行情服务器没有连接");
81 | return;
82 | }
83 |
84 | bool bSubscribe = false;
85 | bool bTrade = false;
86 | bool bQuote = false;
87 | bool bMarketDepth = false;
88 | if (request.NoMDEntryTypes > 0)
89 | {
90 | switch (request.GetMDEntryTypesGroup(0).MDEntryType)
91 | {
92 | case FIXMDEntryType.Bid:
93 | case FIXMDEntryType.Offer:
94 | if (request.MarketDepth != 1)
95 | {
96 | bMarketDepth = true;
97 | break;
98 | }
99 | bQuote = true;
100 | break;
101 | case FIXMDEntryType.Trade:
102 | bTrade = true;
103 | break;
104 | }
105 | }
106 | bSubscribe = (request.SubscriptionRequestType == DataManager.MARKET_DATA_SUBSCRIBE);
107 |
108 | if (bSubscribe)
109 | {
110 | for (int i = 0; i < request.NoRelatedSym; ++i)
111 | {
112 | FIXRelatedSymGroup group = request.GetRelatedSymGroup(i);
113 | Instrument inst = InstrumentManager.Instruments[group.Symbol];
114 |
115 | //将用户合约转成交易所合约
116 | string altSymbol = inst.GetSymbol(this.Name);
117 | string altExchange = inst.GetSecurityExchange(this.Name);
118 | string apiSymbol = GetApiSymbol(altSymbol);
119 | string apiExchange = altExchange;
120 | #if CTPZQ
121 | altSymbol = GetYahooSymbol(apiSymbol, apiExchange);
122 | #endif
123 | CThostFtdcInstrumentField _Instrument;
124 | if (_dictInstruments.TryGetValue(altSymbol, out _Instrument))
125 | {
126 | apiSymbol = _Instrument.InstrumentID;
127 | apiExchange = _Instrument.ExchangeID;
128 | }
129 |
130 | #if CTPZQ
131 | altSymbol = GetYahooSymbol(apiSymbol, apiExchange);
132 | #endif
133 | DataRecord record;
134 | if (!_dictAltSymbol2Instrument.TryGetValue(altSymbol, out record))
135 | {
136 | record = new DataRecord();
137 | record.Instrument = inst;
138 | record.Symbol = apiSymbol;
139 | record.Exchange = apiExchange;
140 | _dictAltSymbol2Instrument[altSymbol] = record;
141 |
142 | mdlog.Info("订阅合约/订阅询价 {0} {1} {2}", altSymbol, record.Symbol, record.Exchange);
143 |
144 | if (_bTdConnected)
145 | {
146 | TraderApi.TD_ReqQryInvestorPosition(m_pTdApi, null);
147 | timerPonstion.Enabled = false;
148 | timerPonstion.Enabled = true;
149 | }
150 | }
151 |
152 | //记录行情,同时对用户合约与交易所合约进行映射
153 | CThostFtdcDepthMarketDataField DepthMarket;
154 | if (!_dictDepthMarketData.TryGetValue(altSymbol, out DepthMarket))
155 | {
156 | _dictDepthMarketData[altSymbol] = DepthMarket;
157 | }
158 |
159 | // 多次订阅也无所谓
160 | MdApi.MD_Subscribe(m_pMdApi, record.Symbol, record.Exchange);
161 | MdApi.MD_SubscribeQuote(m_pMdApi, record.Symbol, record.Exchange);
162 |
163 | if (bTrade)
164 | record.TradeRequested = true;
165 | if (bQuote)
166 | record.QuoteRequested = true;
167 | if (bMarketDepth)
168 | record.MarketDepthRequested = true;
169 |
170 | if (bMarketDepth)
171 | {
172 | inst.OrderBook.Clear();
173 | }
174 | }
175 | }
176 | else
177 | {
178 | for (int i = 0; i < request.NoRelatedSym; ++i)
179 | {
180 | FIXRelatedSymGroup group = request.GetRelatedSymGroup(i);
181 | Instrument inst = InstrumentManager.Instruments[group.Symbol];
182 |
183 | //将用户合约转成交易所合约
184 | string altSymbol = inst.GetSymbol(this.Name);
185 | string altExchange = inst.GetSecurityExchange(this.Name);
186 |
187 | DataRecord record;
188 | if (!_dictAltSymbol2Instrument.TryGetValue(altSymbol, out record))
189 | {
190 | break;
191 | }
192 |
193 | if (bTrade)
194 | record.TradeRequested = false;
195 | if (bQuote)
196 | record.QuoteRequested = false;
197 | if (bMarketDepth)
198 | record.MarketDepthRequested = false;
199 |
200 | if (!record.TradeRequested && !record.QuoteRequested && !record.MarketDepthRequested)
201 | {
202 | _dictDepthMarketData.Remove(altSymbol);
203 | _dictAltSymbol2Instrument.Remove(altSymbol);
204 | mdlog.Info("取消合约/取消询价 {0} {1} {2}", altSymbol, record.Symbol, record.Exchange);
205 | MdApi.MD_Unsubscribe(m_pMdApi, record.Symbol, record.Exchange);
206 | MdApi.MD_UnsubscribeQuote(m_pMdApi, record.Symbol, record.Exchange);
207 | }
208 | else
209 | {
210 | // 只要有一种类型说要订阅,就给订上
211 | MdApi.MD_Subscribe(m_pMdApi, record.Symbol, record.Exchange);
212 | MdApi.MD_SubscribeQuote(m_pMdApi, record.Symbol, record.Exchange);
213 | }
214 | }
215 | }
216 | }
217 |
218 | private bool EmitNewMarketDepth(Instrument instrument, DateTime datatime, int position, MDSide ask, double price, int size)
219 | {
220 | bool bRet = false;
221 | MDOperation insert = MDOperation.Update;
222 | if (MDSide.Ask == ask)
223 | {
224 | if (position >= instrument.OrderBook.Ask.Count)
225 | {
226 | insert = MDOperation.Insert;
227 | }
228 | }
229 | else
230 | {
231 | if (position >= instrument.OrderBook.Bid.Count)
232 | {
233 | insert = MDOperation.Insert;
234 | }
235 | }
236 |
237 | if (price != 0 && size != 0)
238 | {
239 | EmitNewMarketDepth(instrument, new MarketDepth(datatime, "", position, insert, ask, price, size));
240 | bRet = true;
241 | }
242 | return bRet;
243 | }
244 |
245 | private void EmitNewMarketDepth(IFIXInstrument instrument, MarketDepth marketDepth)
246 | {
247 | if (NewMarketDepth != null)
248 | {
249 | NewMarketDepth(this, new MarketDepthEventArgs(marketDepth, instrument, this));
250 | }
251 | }
252 | #endregion
253 |
254 | private void OnNewBar(object sender, BarEventArgs args)
255 | {
256 | if (NewBar != null)
257 | {
258 | CThostFtdcDepthMarketDataField DepthMarket;
259 | Instrument inst = InstrumentManager.Instruments[args.Instrument.Symbol];
260 | string altSymbol = inst.GetSymbol(Name);
261 |
262 | Bar bar = args.Bar;
263 | if (_dictDepthMarketData.TryGetValue(altSymbol, out DepthMarket))
264 | {
265 | bar = new Bar(args.Bar);
266 | bar.OpenInt = (long)DepthMarket.OpenInterest;
267 | }
268 | #if OQ
269 | if (null != MarketDataFilter)
270 | {
271 | Bar b = MarketDataFilter.FilterBar(bar, args.Instrument.Symbol);
272 | if (null != b)
273 | {
274 | NewBar(this, new BarEventArgs(b, args.Instrument, this));
275 | }
276 | }
277 | else
278 | #endif
279 | {
280 | NewBar(this, new BarEventArgs(bar, args.Instrument, this));
281 | }
282 | }
283 | }
284 |
285 | private void OnNewBarOpen(object sender, BarEventArgs args)
286 | {
287 | if (NewBarOpen != null)
288 | {
289 | CThostFtdcDepthMarketDataField DepthMarket;
290 | Instrument inst = InstrumentManager.Instruments[args.Instrument.Symbol];
291 | string altSymbol = inst.GetSymbol(Name);
292 |
293 | Bar bar = args.Bar;
294 | if (_dictDepthMarketData.TryGetValue(altSymbol, out DepthMarket))
295 | {
296 | bar = new Bar(args.Bar);
297 | bar.OpenInt = (long)DepthMarket.OpenInterest;
298 | }
299 |
300 | #if OQ
301 | if (null != MarketDataFilter)
302 | {
303 | Bar b = MarketDataFilter.FilterBarOpen(bar, args.Instrument.Symbol);
304 | if (null != b)
305 | {
306 | NewBarOpen(this, new BarEventArgs(b, args.Instrument, this));
307 | }
308 | }
309 | else
310 | #endif
311 | {
312 | NewBarOpen(this, new BarEventArgs(bar, args.Instrument, this));
313 | }
314 | }
315 | }
316 |
317 | private void EmitNewQuoteEvent(IFIXInstrument instrument, Quote quote)
318 | {
319 | #if OQ
320 | if (this.MarketDataFilter != null)
321 | {
322 | quote = this.MarketDataFilter.FilterQuote(quote, instrument.Symbol);
323 | }
324 | #endif
325 | if (quote != null)
326 | {
327 | if (NewQuote != null)
328 | {
329 | NewQuote(this, new QuoteEventArgs(quote, instrument, this));
330 | }
331 | if (factory != null)
332 | {
333 | factory.OnNewQuote(instrument, quote);
334 | }
335 | }
336 | }
337 |
338 | private void EmitNewTradeEvent(IFIXInstrument instrument, Trade trade)
339 | {
340 | #if OQ
341 | if (this.MarketDataFilter != null)
342 | {
343 | trade = this.MarketDataFilter.FilterTrade(trade, instrument.Symbol);
344 | }
345 | #endif
346 | if (trade != null)
347 | {
348 | if (NewTrade != null)
349 | {
350 | NewTrade(this, new TradeEventArgs(trade, instrument, this));
351 | }
352 | if (factory != null)
353 | {
354 | factory.OnNewTrade(instrument, trade);
355 | }
356 | }
357 | }
358 | }
359 | }
360 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.Provider.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using NLog.Config;
3 | using SmartQuant;
4 | using SmartQuant.Providers;
5 | using System;
6 | using System.Collections.Specialized;
7 | using System.ComponentModel;
8 | using System.IO;
9 | using System.Reflection;
10 | using System.Windows.Forms;
11 |
12 | #if CTP
13 | using QuantBox.CSharp2CTP;
14 | using QuantBox.Helper.CTP;
15 | using System.Collections.Generic;
16 |
17 | namespace QuantBox.OQ.CTP
18 | #elif CTPZQ
19 | using QuantBox.CSharp2CTPZQ;
20 | using QuantBox.Helper.CTPZQ;
21 |
22 | namespace QuantBox.OQ.CTPZQ
23 | #endif
24 | {
25 | public partial class APIProvider : IProvider, IDisposable
26 | {
27 | private byte _Id;
28 | private string _Name;
29 |
30 | private ProviderStatus status;
31 | private bool isConnected;
32 |
33 | public event EventHandler Connected;
34 | public event EventHandler Disconnected;
35 | public event ProviderErrorEventHandler Error;
36 |
37 | private bool disposed;
38 |
39 | private Logger mdlog;
40 | private Logger tdlog;
41 |
42 | // Use C# destructor syntax for finalization code.
43 | ~APIProvider()
44 | {
45 | // Simply call Dispose(false).
46 | Dispose(false);
47 | }
48 |
49 | static bool bDoOnce = true;
50 | public APIProvider()
51 | {
52 | #if CTP
53 | if (bDoOnce)
54 | {
55 | Init(55, "CTP");
56 | bDoOnce = false;
57 |
58 | // 在QR中用多Provider变相实现多账号功能
59 | //new APIProvider().Init(100, "CTP100");
60 | //new APIProvider().Init(101, "CTP101");
61 | //new APIProvider().Init(102, "CTP102");
62 | //new APIProvider().Init(103, "CTP103");
63 | //new APIProvider().Init(104, "CTP104");
64 | //new APIProvider().Init(105, "CTP105");
65 | }
66 | #elif CTPZQ
67 | Init(56,"CTPZQ");
68 | #endif
69 | }
70 |
71 | public void Init(byte Id,string Name)
72 | {
73 | _Id = Id;
74 | _Name = Name;
75 |
76 | mdlog = LogManager.GetLogger(Name + ".M");
77 | tdlog = LogManager.GetLogger(Name + ".T");
78 |
79 | try
80 | {
81 | LogManager.Configuration = new XmlLoggingConfiguration(@"Bin/QuantBox.nlog");
82 | }
83 | catch (Exception ex)
84 | {
85 | tdlog.Warn(ex.Message);
86 | }
87 |
88 | timerConnect.Elapsed += timerConnect_Elapsed;
89 | timerDisconnect.Elapsed += timerDisconnect_Elapsed;
90 | timerAccount.Elapsed += timerAccount_Elapsed;
91 | timerPonstion.Elapsed += timerPonstion_Elapsed;
92 |
93 | InitCallbacks();
94 | InitSettings();
95 |
96 | BarFactory = new SmartQuant.Providers.BarFactory();
97 | status = ProviderStatus.Unknown;
98 | SmartQuant.Providers.ProviderManager.Add(this);
99 | }
100 |
101 | //Implement IDisposable.
102 | public void Dispose()
103 | {
104 | Dispose(true);
105 | GC.SuppressFinalize(this);
106 | }
107 |
108 | protected virtual void Dispose(bool disposing)
109 | {
110 | if (!disposed)
111 | {
112 | if (disposing)
113 | {
114 | // Free other state (managed objects).
115 | }
116 | // Free your own state (unmanaged objects).
117 | // Set large fields to null.
118 | Shutdown();
119 | disposed = true;
120 | }
121 | //base.Dispose(disposing);
122 | }
123 |
124 |
125 |
126 | #region IProvider
127 | [Category(CATEGORY_INFO)]
128 | public byte Id//不能与已经安装的插件ID重复
129 | {
130 | get { return _Id; }
131 | set { _Id = value; }
132 | }
133 |
134 | [Category(CATEGORY_INFO)]
135 | public string Name
136 | {
137 | get { return _Name; }
138 | set { _Name = value; }
139 | }
140 |
141 | [Category(CATEGORY_INFO)]
142 | public string Title
143 | {
144 | get { return string.Format("QuantBox {0} Provider",this.Name); }
145 | }
146 |
147 | [Category(CATEGORY_INFO)]
148 | public string URL
149 | {
150 | get { return "www.quantbox.cn"; }
151 | }
152 |
153 | [Category(CATEGORY_INFO)]
154 | [Description("插件版本信息")]
155 | public string Version
156 | {
157 | get { return Assembly.GetExecutingAssembly().GetName().Version.ToString(); }
158 | }
159 |
160 | [Category(CATEGORY_STATUS)]
161 | public bool IsConnected
162 | {
163 | get { return isConnected; }
164 | }
165 |
166 | [Category(CATEGORY_STATUS)]
167 | public ProviderStatus Status
168 | {
169 | get { return status; }
170 | }
171 |
172 | public void Connect(int timeout)
173 | {
174 | Connect();
175 | ProviderManager.WaitConnected(this, timeout);
176 | }
177 |
178 | public void Connect()
179 | {
180 | _Connect();
181 | }
182 |
183 | public void Disconnect()
184 | {
185 | _Disconnect();
186 | }
187 |
188 | public void Shutdown()
189 | {
190 | Disconnect();
191 |
192 | SettingsChanged();
193 |
194 | timerConnect.Elapsed -= timerConnect_Elapsed;
195 | timerDisconnect.Elapsed -= timerDisconnect_Elapsed;
196 | timerAccount.Elapsed -= timerAccount_Elapsed;
197 | timerPonstion.Elapsed -= timerPonstion_Elapsed;
198 | }
199 |
200 | public event EventHandler StatusChanged;
201 |
202 | private void ChangeStatus(ProviderStatus status)
203 | {
204 | this.status = status;
205 | EmitStatusChangedEvent();
206 | }
207 |
208 | private void EmitStatusChangedEvent()
209 | {
210 | if (StatusChanged != null)
211 | {
212 | StatusChanged(this, EventArgs.Empty);
213 | }
214 | }
215 |
216 | private void EmitConnectedEvent()
217 | {
218 | if (Connected != null)
219 | {
220 | Connected(this, EventArgs.Empty);
221 | }
222 | }
223 |
224 | private void EmitDisconnectedEvent()
225 | {
226 | if (Disconnected != null)
227 | {
228 | Disconnected(this, EventArgs.Empty);
229 | }
230 | }
231 |
232 | private void EmitError(int id, int code, string message)
233 | {
234 | if (Error != null)
235 | Error(new ProviderErrorEventArgs(new ProviderError(Clock.Now, this, id, code, message)));
236 | }
237 | #endregion
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.Settings.cs:
--------------------------------------------------------------------------------
1 | using SmartQuant;
2 | using System;
3 | using System.ComponentModel;
4 | using System.Drawing.Design;
5 | using System.IO;
6 | using System.Xml.Serialization;
7 | using QuantBox.OQ.CTP;
8 | using QuantBox.OQ.Extensions;
9 |
10 | #if CTP
11 | using QuantBox.CSharp2CTP;
12 | using QuantBox.Helper.CTP;
13 |
14 | namespace QuantBox.OQ.CTP
15 | #elif CTPZQ
16 | using QuantBox.CSharp2CTPZQ;
17 | using QuantBox.Helper.CTPZQ;
18 |
19 | namespace QuantBox.OQ.CTPZQ
20 | #endif
21 | {
22 | partial class APIProvider
23 | {
24 | private const string CATEGORY_ACCOUNT = "Account";
25 | private const string CATEGORY_BARFACTORY = "Bar Factory";
26 | private const string CATEGORY_DEBUG = "Debug";
27 | private const string CATEGORY_EXECUTION = "Settings - Execution";
28 | private const string CATEGORY_HISTORICAL = "Settings - Historical Data";
29 | private const string CATEGORY_INFO = "Information";
30 | private const string CATEGORY_NETWORK = "Settings - Network";
31 | private const string CATEGORY_STATUS = "Status";
32 | private const string CATEGORY_TIME = "Settings - Time";
33 | private const string CATEGORY_OTHER = "Settings - Other";
34 |
35 |
36 | public string accountsFile;
37 | public string serversFile;
38 | public string brokersFile;
39 |
40 | #if CTP
41 | //交易所常量定义
42 | private enum ExchangID
43 | {
44 | SHFE,
45 | DCE,
46 | CZCE,
47 | CFFEX
48 | }
49 |
50 | private string _SupportMarketOrder;
51 | private string _SupportCloseToday;
52 |
53 |
54 | [Category(CATEGORY_OTHER)]
55 | [Description("支持市价单的交易所")]
56 | public string SupportMarketOrder
57 | {
58 | get { return _SupportMarketOrder; }
59 | }
60 |
61 |
62 | [Category(CATEGORY_OTHER)]
63 | [Description("区分平今与平昨的交易所")]
64 | public string SupportCloseToday
65 | {
66 | get { return _SupportCloseToday; }
67 | }
68 |
69 |
70 |
71 | #elif CTPZQ
72 | private enum ExchangID
73 | {
74 | SSE,
75 | SZE
76 | }
77 | #endif
78 | private EnumOpenClose _DefaultOpenClose;
79 |
80 | [DefaultValue(EnumOpenClose.OPEN)]
81 | [Category(CATEGORY_OTHER)]
82 | [Description("默认开平:当没有指定开平时,按此进行开平")]
83 | public EnumOpenClose DefaultOpenClose
84 | {
85 | get { return _DefaultOpenClose; }
86 | set { _DefaultOpenClose = value; }
87 | }
88 |
89 | public enum TimeMode
90 | {
91 | LocalTime,
92 | ExchangeTime
93 | }
94 |
95 | public enum SetTimeMode
96 | {
97 | None,
98 | LoginTime,
99 | SHFETime,
100 | DCETime,
101 | CZCETime,
102 | FFEXTime
103 | }
104 |
105 | #region 参数设置
106 | private TimeMode _TimeMode;
107 |
108 | [Category(CATEGORY_OTHER)]
109 | [Description("设置API生成临时文件的目录")]
110 | [Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
111 | [Browsable(false)]
112 | public string ApiTempPath { get; set; }
113 |
114 | [Category(CATEGORY_TIME)]
115 | [Description("警告!仅保存行情数据时才用交易所时间。交易时使用交易所时间将导致Bar生成错误")]
116 | [DefaultValue(TimeMode.LocalTime)]
117 | public TimeMode DateTimeMode
118 | {
119 | get { return _TimeMode; }
120 | set { _TimeMode = value; }
121 | }
122 |
123 | [Category(CATEGORY_TIME)]
124 | [Description("修改本地时间。分别是:不修改、登录交易前置机时间、各大交易所时间。以管理员方式运行才有权限")]
125 | [DefaultValue(SetTimeMode.None)]
126 | public SetTimeMode SetLocalTimeMode
127 | {
128 | get;
129 | set;
130 | }
131 |
132 | [Category(CATEGORY_TIME)]
133 | [DefaultValue(0)]
134 | [Description("修改本地时间时,在取到的时间上添加指定毫秒")]
135 | public int AddMilliseconds
136 | {
137 | get;
138 | set;
139 | }
140 |
141 | [Category(CATEGORY_OTHER)]
142 | [Description("设置登录后是否接收完整的报单和成交记录")]
143 | [DefaultValue(THOST_TE_RESUME_TYPE.THOST_TERT_QUICK)]
144 | public THOST_TE_RESUME_TYPE ResumeType { get; set; }
145 |
146 | [Category(CATEGORY_OTHER)]
147 | [Description("设置投机套保标志。\nSpeculation - 投机\nArbitrage - 套利\nHedge - 套保")]
148 | [DefaultValue(TThostFtdcHedgeFlagType.Speculation)]
149 | public TThostFtdcHedgeFlagType HedgeFlagType
150 | {
151 | get;
152 | set;
153 | }
154 |
155 |
156 |
157 | [Category(CATEGORY_OTHER)]
158 | [Description("在最新价上调整N跳来模拟市价,超过涨跌停价按涨跌停价报单")]
159 | [DefaultValue(10)]
160 | public int LastPricePlusNTicks
161 | {
162 | get;
163 | set;
164 | }
165 |
166 | [Category(CATEGORY_OTHER)]
167 | [Description("True - 所有市价单都用限价单来模拟\nFalse - 仅对上期所进行模拟")]
168 | [DefaultValue(false)]
169 | public bool SwitchMakertOrderToLimitOrder
170 | {
171 | get;
172 | set;
173 | }
174 |
175 | private BindingList serversList = new BindingList();
176 | [Category("Settings")]
177 | [Description("服务器信息,只选择第一条登录")]
178 | public BindingList Server
179 | {
180 | get { return serversList; }
181 | set { serversList = value; }
182 | }
183 |
184 | private BindingList accountsList = new BindingList();
185 | [Category("Settings")]
186 | [Description("账号信息,只选择第一条登录")]
187 | public BindingList Account
188 | {
189 | get { return accountsList; }
190 | set { accountsList = value; }
191 | }
192 |
193 | private BindingList brokersList = new BindingList();
194 | [Category("Settings"), Editor(typeof(ServersManagerTypeEditor), typeof(UITypeEditor)),
195 | Description("点击(...)查看经纪商列表")]
196 | public BindingList Brokers
197 | {
198 | get { return brokersList; }
199 | set { brokersList = value; }
200 | }
201 |
202 | [Category("Settings")]
203 | [Description("连接到行情。此插件不连接行情时底层对不支持市价的报单不会做涨跌停修正,需策略层处理")]
204 | [DefaultValue(true)]
205 | public bool ConnectToMarketData
206 | {
207 | get { return _bWantMdConnect; }
208 | set { _bWantMdConnect = value; }
209 | }
210 |
211 | [Category("Settings")]
212 | [Description("连接到交易")]
213 | [DefaultValue(true)]
214 | public bool ConnectToTrading
215 | {
216 | get { return _bWantTdConnect; }
217 | set { _bWantTdConnect = value; }
218 | }
219 |
220 | #endregion
221 | private void InitSettings()
222 | {
223 | accountsFile = string.Format(@"{0}\{1}.Accounts.xml", Framework.Installation.IniDir,this.Name);
224 | serversFile = string.Format(@"{0}\{1}.Servers.xml", Framework.Installation.IniDir, this.Name);
225 | brokersFile = string.Format(@"{0}\{1}.Brokers.xml", Framework.Installation.IniDir, this.Name);
226 |
227 | ApiTempPath = Framework.Installation.TempDir.FullName;
228 | ResumeType = THOST_TE_RESUME_TYPE.THOST_TERT_QUICK;
229 | HedgeFlagType = TThostFtdcHedgeFlagType.Speculation;
230 | _DefaultOpenClose = EnumOpenClose.OPEN;
231 |
232 | SwitchMakertOrderToLimitOrder = false;
233 |
234 | _bWantMdConnect = true;
235 | _bWantTdConnect = true;
236 |
237 | #if CTP
238 | _SupportMarketOrder = String.Format("{0};{1};{2};", ExchangID.DCE, ExchangID.CZCE, ExchangID.CFFEX);
239 | _SupportCloseToday = ExchangID.SHFE + ";";
240 |
241 | #elif CTPZQ
242 |
243 | #endif
244 | LastPricePlusNTicks = 10;
245 |
246 | LoadAccounts();
247 | LoadServers();
248 |
249 | serversList.ListChanged += ServersList_ListChanged;
250 | accountsList.ListChanged += AccountsList_ListChanged;
251 | }
252 |
253 | void ServersList_ListChanged(object sender, ListChangedEventArgs e)
254 | {
255 | if (e.ListChangedType == ListChangedType.ItemAdded)
256 | {
257 | serversList[e.NewIndex].Changed += ServerItem_ListChanged;
258 | }
259 | SettingsChanged();
260 | }
261 |
262 | void AccountsList_ListChanged(object sender, EventArgs e)
263 | {
264 | SettingsChanged();
265 | }
266 |
267 | void ServerItem_ListChanged(object sender, EventArgs e)
268 | {
269 | SettingsChanged();
270 | }
271 |
272 | public void SettingsChanged()
273 | {
274 | SaveAccounts();
275 | SaveServers();
276 | }
277 |
278 |
279 | void LoadAccounts()
280 | {
281 | accountsList.Clear();
282 |
283 | try
284 | {
285 | XmlSerializer serializer = new XmlSerializer(accountsList.GetType());
286 | using (FileStream stream = new FileStream(accountsFile, FileMode.Open))
287 | {
288 | accountsList = (BindingList)serializer.Deserialize(stream);
289 | stream.Close();
290 | }
291 | }
292 | catch (Exception)
293 | {
294 | }
295 | }
296 |
297 | void SaveAccounts()
298 | {
299 | XmlSerializer serializer = new XmlSerializer(accountsList.GetType());
300 | using (TextWriter writer = new StreamWriter(accountsFile))
301 | {
302 | serializer.Serialize(writer, accountsList);
303 | writer.Close();
304 | }
305 | }
306 |
307 | void LoadServers()
308 | {
309 | serversList.Clear();
310 |
311 | try
312 | {
313 | XmlSerializer serializer = new XmlSerializer(serversList.GetType());
314 | using (FileStream stream = new FileStream(serversFile, FileMode.Open))
315 | {
316 | serversList = (BindingList)serializer.Deserialize(stream);
317 | stream.Close();
318 | }
319 | }
320 | catch (Exception)
321 | {
322 | }
323 | }
324 |
325 | void SaveServers()
326 | {
327 | XmlSerializer serializer = new XmlSerializer(serversList.GetType());
328 | using (TextWriter writer = new StreamWriter(serversFile))
329 | {
330 | serializer.Serialize(writer, serversList);
331 | writer.Close();
332 | }
333 | }
334 |
335 | public void LoadBrokers()
336 | {
337 | brokersList.Clear();
338 |
339 | try
340 | {
341 | XmlSerializer serializer = new XmlSerializer(brokersList.GetType());
342 | using (FileStream stream = new FileStream(brokersFile, FileMode.Open))
343 | {
344 | brokersList = (BindingList)serializer.Deserialize(stream);
345 | stream.Close();
346 | }
347 | }
348 | catch (Exception)
349 | {
350 | }
351 | }
352 |
353 | void SaveBrokers()
354 | {
355 | XmlSerializer serializer = new XmlSerializer(brokersList.GetType());
356 | using (TextWriter writer = new StreamWriter(brokersFile))
357 | {
358 | serializer.Serialize(writer, brokersList);
359 | writer.Close();
360 | }
361 | }
362 | }
363 | }
364 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/APIProvider.SimulationMarketDataProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | using SmartQuant.Data;
5 | using SmartQuant.FIX;
6 | using SmartQuant.Instruments;
7 | using SmartQuant.Providers;
8 |
9 | #if CTP
10 | using QuantBox.CSharp2CTP;
11 | using QuantBox.Helper.CTP;
12 |
13 | namespace QuantBox.OQ.CTP
14 | #elif CTPZQ
15 | using QuantBox.CSharp2CTPZQ;
16 | using QuantBox.Helper.CTPZQ;
17 |
18 | namespace QuantBox.OQ.CTPZQ
19 | #endif
20 | {
21 | public partial class APIProvider :ISimulationMarketDataProvider
22 | {
23 | #region OpenQuant3接口的新方法
24 | public void EmitQuote(IFIXInstrument instrument, Quote quote)
25 | {
26 | EmitNewQuoteEvent(instrument, quote);
27 | }
28 |
29 | public void EmitTrade(IFIXInstrument instrument, Trade trade)
30 | {
31 | EmitNewTradeEvent(instrument, trade);
32 | }
33 | #endregion
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/AccountItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.ComponentModel;
6 |
7 | namespace QuantBox.OQ.CTP
8 | {
9 | [DefaultPropertyAttribute("Label")]
10 | public class AccountItem
11 | {
12 | [DescriptionAttribute("账号")]
13 | public string InvestorId
14 | {
15 | get;
16 | set;
17 | }
18 | [PasswordPropertyText(true)]
19 | [DescriptionAttribute("密码")]
20 | public string Password
21 | {
22 | get;
23 | set;
24 | }
25 |
26 | [CategoryAttribute("标签"),
27 | DescriptionAttribute("标签不能重复")]
28 | public string Label
29 | {
30 | get;
31 | set;
32 | }
33 |
34 | public override string ToString()
35 | {
36 | return "标签不能重复";
37 | }
38 |
39 | [BrowsableAttribute(false)]
40 | public string Name
41 | {
42 | get { return Label; }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/ApiContainer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace QuantBox.OQ.CTP
7 | {
8 | public class ApiContainer
9 | {
10 | private Dictionary string_T = new Dictionary();
11 | private Dictionary IntPtr_T = new Dictionary();
12 |
13 | public T this[string account]
14 | {
15 | get
16 | {
17 | return string_T[account];
18 | }
19 | //set
20 | //{
21 | // string_T[account] = value;
22 | //}
23 | }
24 |
25 | public T this[IntPtr ptr]
26 | {
27 | get
28 | {
29 | return IntPtr_T[ptr];
30 | }
31 | //set
32 | //{
33 | // IntPtr_T[ptr] = value;
34 | //}
35 | }
36 |
37 | public void Add(string account, T t)
38 | {
39 | string_T[account] = t;
40 | }
41 |
42 | public void Add(IntPtr ptr, T t)
43 | {
44 | IntPtr_T[ptr] = t;
45 | }
46 |
47 | public void Remove(IntPtr ptr)
48 | {
49 | }
50 | public void Remove(string account)
51 | {
52 | }
53 | public void Remove(ApiWrapper api)
54 | {
55 | }
56 | public void Remove(int index)
57 | {
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/ApiWrapper.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using QuantBox.CSharp2CTP;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 |
8 | namespace QuantBox.OQ.CTP
9 | {
10 | public class ApiWrapper
11 | {
12 | public Logger Log;
13 |
14 | public fnOnConnect _fnOnConnect_Holder;
15 | public fnOnDisconnect _fnOnDisconnect_Holder;
16 | public fnOnRspError _fnOnRspError_Holder;
17 |
18 | public ServerItem server;
19 | public AccountItem account;
20 |
21 | protected string tempPath;
22 |
23 | protected readonly object _lock = new object();
24 | private readonly object _lockMsgQueue = new object();
25 |
26 | protected IntPtr m_pMsgQueue = IntPtr.Zero;
27 | protected IntPtr Api = IntPtr.Zero;
28 |
29 | public volatile bool IsConnected;
30 |
31 | protected void Connect_MsgQueue()
32 | {
33 | lock (_lockMsgQueue)
34 | {
35 | if (null == m_pMsgQueue || IntPtr.Zero == m_pMsgQueue)
36 | {
37 | m_pMsgQueue = CommApi.CTP_CreateMsgQueue();
38 |
39 | CommApi.CTP_RegOnConnect(m_pMsgQueue, _fnOnConnect_Holder);
40 | CommApi.CTP_RegOnDisconnect(m_pMsgQueue, _fnOnDisconnect_Holder);
41 | CommApi.CTP_RegOnRspError(m_pMsgQueue, _fnOnRspError_Holder);
42 |
43 | CommApi.CTP_StartMsgQueue(m_pMsgQueue);
44 | }
45 | }
46 | }
47 |
48 | protected void Disconnect_MsgQueue()
49 | {
50 | lock (_lockMsgQueue)
51 | {
52 | if (null != m_pMsgQueue && IntPtr.Zero != m_pMsgQueue)
53 | {
54 | CommApi.CTP_StopMsgQueue(m_pMsgQueue);
55 |
56 | CommApi.CTP_ReleaseMsgQueue(m_pMsgQueue);
57 | m_pMsgQueue = IntPtr.Zero;
58 | }
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/BrokerItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace QuantBox.OQ.CTP
8 | {
9 | public class BrokerItem
10 | {
11 | public string Label
12 | {
13 | get;
14 | set;
15 | }
16 |
17 | public BindingList Server
18 | {
19 | get;
20 | set;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/DataRecord.cs:
--------------------------------------------------------------------------------
1 | using SmartQuant.Instruments;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace QuantBox.OQ.CTP
8 | {
9 | class DataRecord
10 | {
11 | public string Symbol;
12 | public string Exchange;
13 | public Instrument Instrument;
14 | public bool TradeRequested;
15 | public bool QuoteRequested;
16 | public bool MarketDepthRequested;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/OrderMap.cs:
--------------------------------------------------------------------------------
1 | using QuantBox.OQ.Extensions.OrderItem;
2 | using SmartQuant.Execution;
3 | using SmartQuant.FIX;
4 | using System.Collections.Generic;
5 |
6 | #if CTP
7 | using QuantBox.CSharp2CTP;
8 |
9 | namespace QuantBox.OQ.CTP
10 | #elif CTPZQ
11 | using QuantBox.CSharp2CTPZQ;
12 |
13 | namespace QuantBox.OQ.CTPZQ
14 | #endif
15 | {
16 | public class OrderMap
17 | {
18 | // API中的报单引用,一个Ref只对应一个报单组合
19 | public readonly Dictionary OrderRef_OrderItem = new Dictionary();
20 | // 记录界面报单到报单组合的关系
21 | public readonly Dictionary Order_OrderItem = new Dictionary();
22 | // 记录报单组合到报单回报的关系,用于撤单
23 | public readonly Dictionary OrderItem_OrderField = new Dictionary();
24 | // 交易所信息映射到本地信息
25 | public readonly Dictionary OrderSysID_OrderRef = new Dictionary();
26 | // 标记正在撤单
27 | public readonly Dictionary Order_OrdStatus = new Dictionary();
28 |
29 | public void Clear()
30 | {
31 | OrderRef_OrderItem.Clear();
32 | Order_OrderItem.Clear();
33 | OrderItem_OrderField.Clear();
34 | OrderSysID_OrderRef.Clear();
35 | Order_OrdStatus.Clear();
36 | }
37 |
38 | // 用于收到委托回报信息后进行处理
39 | public bool TryGetValue(string key,out GenericOrderItem value)
40 | {
41 | return OrderRef_OrderItem.TryGetValue(key, out value);
42 | }
43 |
44 | // 用于收到成交回报信息后找到原始的报单引用
45 | public bool TryGetValue(string key, out string value)
46 | {
47 | return OrderSysID_OrderRef.TryGetValue(key, out value);
48 | }
49 |
50 | // 界面撤单时用于找到对应的报单组合
51 | public bool TryGetValue(SingleOrder key, out GenericOrderItem value)
52 | {
53 | return Order_OrderItem.TryGetValue(key, out value);
54 | }
55 |
56 | // 通过报单组合,实际的向交易所撤单
57 | public bool TryGetValue(GenericOrderItem key, out CThostFtdcOrderField value)
58 | {
59 | return OrderItem_OrderField.TryGetValue(key, out value);
60 | }
61 |
62 | // 返回状态
63 | public bool TryGetValue(SingleOrder key, out OrdStatus value)
64 | {
65 | return Order_OrdStatus.TryGetValue(key, out value);
66 | }
67 |
68 | public void CreateNewOrder(string key,GenericOrderItem value)
69 | {
70 | OrderRef_OrderItem[key] = value;
71 | }
72 |
73 | // 通过一个报单引用,把相关的单子全删了
74 | public void Remove(string key)
75 | {
76 |
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/OrderRecord.cs:
--------------------------------------------------------------------------------
1 | using SmartQuant.Execution;
2 |
3 | namespace QuantBox.OQ.CTP
4 | {
5 | class OrderRecord
6 | {
7 | // Fields
8 | private double avgPx;
9 | private int cumQty;
10 | private int leavesQty;
11 | private SingleOrder order;
12 |
13 | // Methods
14 | public OrderRecord(SingleOrder order)
15 | {
16 | this.order = order;
17 | this.avgPx = 0.0;
18 | this.leavesQty = (int)order.OrderQty;
19 | this.cumQty = 0;
20 | }
21 |
22 | public void AddFill(double lastPx, int lastQty)
23 | {
24 | this.avgPx = ((this.avgPx * this.cumQty) + (lastPx * lastQty)) / ((double)(this.cumQty + lastQty));
25 | this.leavesQty -= lastQty;
26 | this.cumQty += lastQty;
27 | }
28 |
29 | // Properties
30 | public double AvgPx
31 | {
32 | get
33 | {
34 | return this.avgPx;
35 | }
36 | }
37 |
38 | public int CumQty
39 | {
40 | get
41 | {
42 | return this.cumQty;
43 | }
44 | }
45 |
46 | public int LeavesQty
47 | {
48 | get
49 | {
50 | return this.leavesQty;
51 | }
52 | internal set
53 | {
54 | this.leavesQty = value;
55 | }
56 | }
57 |
58 | public SingleOrder Order
59 | {
60 | get
61 | {
62 | return this.order;
63 | }
64 | }
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的常规信息通过以下
6 | // 特性集控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("QuantBox.OQ.CTP")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("QuantBox.cn")]
12 | [assembly: AssemblyProduct("QuantBox.OQ.CTP")]
13 | [assembly: AssemblyCopyright("Copyright © QuantBox.cn 2014")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 使此程序集中的类型
18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
19 | // 则将该类型上的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("dea1de5e-e4af-46bc-aa5e-f0bd13d70c44")]
24 |
25 | // 程序集的版本信息由下面四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 内部版本号
30 | // 修订号
31 | //
32 | // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("4.0.0.14")]
36 | [assembly: AssemblyFileVersion("4.0.0.14")]
37 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/Properties/DataSources/BrokerItem.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | QuantBox.OQ.CTP.BrokerItem, QuantBox.OQ.CTP, Version=3.2.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/Properties/DataSources/ServerItem.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | QuantBox.OQ.CTP.ServerItem, QuantBox.OQ.CTP, Version=3.2.0.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/QuantBox.OQ.CTP.OQ3.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {72BE4BFC-E0F6-436F-8206-C6009932D620}
9 | Library
10 | Properties
11 | QuantBox.OQ.CTP
12 | QuantBox.OQ.CTP
13 | v4.0
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Framework\bin\
22 | TRACE;DEBUG;CTP,OQ
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | ..\..\bin\
30 | TRACE;CTP,OQ
31 | prompt
32 | 4
33 |
34 |
35 |
36 | False
37 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\Newtonsoft.Json.dll
38 |
39 |
40 |
41 | False
42 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTP.dll
43 |
44 |
45 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.Libray.dll
46 |
47 |
48 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll
49 |
50 |
51 | False
52 | ..\reference\using\SmartQuant.dll
53 |
54 |
55 | ..\reference\using\SmartQuant.Data.dll
56 |
57 |
58 | False
59 | ..\reference\using\SmartQuant.Execution.dll
60 |
61 |
62 | False
63 | ..\reference\using\SmartQuant.FIX.dll
64 |
65 |
66 | False
67 | ..\reference\using\SmartQuant.Instruments.dll
68 |
69 |
70 | False
71 | ..\reference\using\SmartQuant.Providers.dll
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 | Form
105 |
106 |
107 | ServersManagerForm.cs
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | ServersManagerForm.cs
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | {97ae93ec-5897-43c8-8d84-d92b73fe1434}
125 | QuantBox.Helper.CTP.Net40
126 |
127 |
128 |
129 |
136 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/QuantBox.OQ.CTP.QD.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {C29F1F5E-C773-4EF1-AD60-2312760276CA}
9 | Library
10 | Properties
11 | QuantBox.OQ.CTP
12 | QuantBox.OQ.CTP
13 | v3.5
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\QuantDeveloper .NET\bin\
22 | TRACE;DEBUG;CTP,QD
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | ..\..\bin\
30 | TRACE;CTP
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 | False
38 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTP.dll
39 |
40 |
41 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll
42 |
43 |
44 | False
45 | ..\reference\using\SmartQuant.dll
46 |
47 |
48 | ..\reference\using\SmartQuant.Data.dll
49 |
50 |
51 | False
52 | ..\reference\using\SmartQuant.Execution.dll
53 |
54 |
55 | False
56 | ..\reference\using\SmartQuant.FIX.dll
57 |
58 |
59 | False
60 | ..\reference\using\SmartQuant.Instruments.dll
61 |
62 |
63 | False
64 | ..\reference\using\SmartQuant.Providers.dll
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 | Form
92 |
93 |
94 | ServersManagerForm.cs
95 |
96 |
97 |
98 |
99 |
100 |
101 | ServersManagerForm.cs
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | {2c5c5377-e34c-4515-9404-3461aae70a8a}
111 | QuantBox.Helper.CTP.Net35
112 |
113 |
114 |
115 |
122 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/QuantBox.OQ.CTPZQ.OQ3.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {49F99E4A-F8D0-4CB8-84B2-39B4F6AC3576}
9 | Library
10 | Properties
11 | QuantBox.OQ.CTPZQ
12 | QuantBox.OQ.CTPZQ
13 | v4.0
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Framework\bin\
22 | TRACE;DEBUG;CTPZQ,OQ
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | ..\..\bin\
30 | TRACE;CTPZQ,OQ
31 | prompt
32 | 4
33 |
34 |
35 |
36 | False
37 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\Newtonsoft.Json.dll
38 |
39 |
40 |
41 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTPZQ.dll
42 |
43 |
44 | False
45 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll
46 |
47 |
48 | False
49 | ..\reference\using\SmartQuant.dll
50 |
51 |
52 | ..\reference\using\SmartQuant.Data.dll
53 |
54 |
55 | False
56 | ..\reference\using\SmartQuant.Execution.dll
57 |
58 |
59 | False
60 | ..\reference\using\SmartQuant.FIX.dll
61 |
62 |
63 | False
64 | ..\reference\using\SmartQuant.Instruments.dll
65 |
66 |
67 | False
68 | ..\reference\using\SmartQuant.Providers.dll
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 | Form
98 |
99 |
100 | ServersManagerForm.cs
101 |
102 |
103 |
104 |
105 |
106 |
107 | ServersManagerForm.cs
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | {5caeb588-ba0f-4313-8b78-5101e97d695a}
117 | QuantBox.Helper.CTPZQ.Net40
118 |
119 |
120 |
121 |
128 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/QuantBox.OQ.CTPZQ.QD.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {38331CDE-8393-490E-B56B-CA5A2E6DE01B}
9 | Library
10 | Properties
11 | QuantBox.OQ.CTPZQ
12 | QuantBox.OQ.CTPZQ
13 | v3.5
14 | 512
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Framework\bin\
22 | TRACE;DEBUG;CTPZQ,QD
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | ..\..\bin\
30 | TRACE;CTPZQ
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 | ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTPZQ.dll
38 |
39 |
40 | False
41 | ..\reference\using\SmartQuant.dll
42 |
43 |
44 | ..\reference\using\SmartQuant.Data.dll
45 |
46 |
47 | False
48 | ..\reference\using\SmartQuant.Execution.dll
49 |
50 |
51 | False
52 | ..\reference\using\SmartQuant.FIX.dll
53 |
54 |
55 | False
56 | ..\reference\using\SmartQuant.Instruments.dll
57 |
58 |
59 | False
60 | ..\reference\using\SmartQuant.Providers.dll
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 | Form
88 |
89 |
90 | ServersManagerForm.cs
91 |
92 |
93 |
94 |
95 |
96 |
97 | ServersManagerForm.cs
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | {4a6b6c0f-d169-4358-b42f-fae8743de897}
107 | QuantBox.Helper.CTPZQ.Net35
108 |
109 |
110 |
111 |
118 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/QuoteApiWrapper.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using QuantBox.CSharp2CTP;
3 | using SmartQuant;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 |
10 | namespace QuantBox.OQ.CTP
11 | {
12 | public class QuoteApiWrapper : ApiWrapper
13 | {
14 | public fnOnRtnDepthMarketData _fnOnRtnDepthMarketData_Holder;
15 |
16 | public void Connect(ServerItem server, AccountItem account)
17 | {
18 | tempPath = Framework.Installation.TempDir.FullName + Path.DirectorySeparatorChar + server.BrokerID + Path.DirectorySeparatorChar + account.InvestorId;
19 | Directory.CreateDirectory(tempPath);
20 |
21 | Disconnect_MD();
22 |
23 | Connect_MsgQueue();
24 | Connect_MD();
25 | }
26 |
27 | public void Disconnect()
28 | {
29 | Disconnect_MD();
30 | Disconnect_MsgQueue();
31 | }
32 |
33 | private void Connect_MD()
34 | {
35 | lock (_lock)
36 | {
37 | if (null == Api || IntPtr.Zero == Api)
38 | {
39 | Api = MdApi.MD_CreateMdApi();
40 | MdApi.CTP_RegOnRtnDepthMarketData(m_pMsgQueue, _fnOnRtnDepthMarketData_Holder);
41 | MdApi.MD_RegMsgQueue2MdApi(Api, m_pMsgQueue);
42 | MdApi.MD_Connect(Api, tempPath, string.Join(";", server.MarketData.ToArray()), server.BrokerID, account.InvestorId, account.Password);
43 | }
44 | }
45 | }
46 |
47 | private void Disconnect_MD()
48 | {
49 | lock (_lock)
50 | {
51 | if (null != Api && IntPtr.Zero != Api)
52 | {
53 | MdApi.MD_RegMsgQueue2MdApi(Api, IntPtr.Zero);
54 | MdApi.MD_ReleaseMdApi(Api);
55 | Api = IntPtr.Zero;
56 | }
57 | IsConnected = false;
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/ServerItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.ComponentModel;
6 |
7 |
8 | namespace QuantBox.OQ.CTP
9 | {
10 | [DefaultPropertyAttribute("Label")]
11 | public class ServerItem
12 | {
13 | private const string OPEN_QUANT = "OpenQuant";
14 | private string userProductInfo = OPEN_QUANT;
15 |
16 | [CategoryAttribute("客户端认证"),
17 | DescriptionAttribute("区别于其它客户端的标识"),
18 | DefaultValue(OPEN_QUANT)]
19 | public string UserProductInfo
20 | {
21 | get { return userProductInfo; }
22 | set { userProductInfo = value; }
23 | }
24 |
25 | [CategoryAttribute("客户端认证"),
26 | DescriptionAttribute("如果不需要认证此处一定要置为空")]
27 | public string AuthCode
28 | {
29 | get;
30 | set;
31 | }
32 |
33 | [CategoryAttribute("服务端信息")]
34 | public string BrokerID
35 | {
36 | get;
37 | set;
38 | }
39 |
40 | private BindingList trading = new BindingList();
41 | [CategoryAttribute("服务端信息"),
42 | DescriptionAttribute("交易服务器地址")]
43 | public BindingList Trading
44 | {
45 | get{ return trading; }
46 | set{ trading = value;}
47 | }
48 |
49 | private BindingList marketData = new BindingList();
50 | [CategoryAttribute("服务端信息"),
51 | DescriptionAttribute("行情服务器地址")]
52 | public BindingList MarketData
53 | {
54 | get { return marketData; }
55 | set { marketData = value; }
56 | }
57 |
58 | [CategoryAttribute("标签"),
59 | DescriptionAttribute("标签不能重复")]
60 | public string Label
61 | {
62 | get;
63 | set;
64 | }
65 |
66 | public override string ToString()
67 | {
68 | return "标签不能重复";
69 | }
70 |
71 | [BrowsableAttribute(false)]
72 | public string Name
73 | {
74 | get { return Label; }
75 | }
76 |
77 | public ServerItem()
78 | {
79 | marketData.ListChanged += Settings_ListChanged;
80 | trading.ListChanged += Settings_ListChanged;
81 | }
82 |
83 | public event EventHandler Changed;
84 |
85 | void Settings_ListChanged(object sender, ListChangedEventArgs e)
86 | {
87 | EventHandler handler = Changed;
88 | if (handler != null)
89 | {
90 | handler(this, EventArgs.Empty);
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/ServersManagerForm.Designer.cs:
--------------------------------------------------------------------------------
1 | #if CTP
2 | namespace QuantBox.OQ.CTP
3 | #elif CTPZQ
4 | namespace QuantBox.OQ.CTPZQ
5 | #endif
6 | {
7 | partial class ServersManagerForm
8 | {
9 | ///
10 | /// Required designer variable.
11 | ///
12 | private System.ComponentModel.IContainer components = null;
13 |
14 | ///
15 | /// Clean up any resources being used.
16 | ///
17 | /// true if managed resources should be disposed; otherwise, false.
18 | protected override void Dispose(bool disposing)
19 | {
20 | if (disposing && (components != null))
21 | {
22 | components.Dispose();
23 | }
24 | base.Dispose(disposing);
25 | }
26 |
27 | #region Windows Form Designer generated code
28 |
29 | ///
30 | /// Required method for Designer support - do not modify
31 | /// the contents of this method with the code editor.
32 | ///
33 | private void InitializeComponent()
34 | {
35 | this.components = new System.ComponentModel.Container();
36 | this.listBoxBroker = new System.Windows.Forms.ListBox();
37 | this.brokerItemBindingSource = new System.Windows.Forms.BindingSource(this.components);
38 | this.listBoxServer = new System.Windows.Forms.ListBox();
39 | this.serverItemBindingSource = new System.Windows.Forms.BindingSource(this.components);
40 | this.buttonAdd = new System.Windows.Forms.Button();
41 | this.buttonRemove = new System.Windows.Forms.Button();
42 | this.textBoxUrl = new System.Windows.Forms.TextBox();
43 | this.buttonUpdate = new System.Windows.Forms.Button();
44 | ((System.ComponentModel.ISupportInitialize)(this.brokerItemBindingSource)).BeginInit();
45 | ((System.ComponentModel.ISupportInitialize)(this.serverItemBindingSource)).BeginInit();
46 | this.SuspendLayout();
47 | //
48 | // listBoxBroker
49 | //
50 | this.listBoxBroker.DataSource = this.brokerItemBindingSource;
51 | this.listBoxBroker.DisplayMember = "Label";
52 | this.listBoxBroker.FormattingEnabled = true;
53 | this.listBoxBroker.Location = new System.Drawing.Point(12, 50);
54 | this.listBoxBroker.Name = "listBoxBroker";
55 | this.listBoxBroker.Size = new System.Drawing.Size(216, 264);
56 | this.listBoxBroker.TabIndex = 0;
57 | //
58 | // brokerItemBindingSource
59 | //
60 | this.brokerItemBindingSource.DataSource = typeof(QuantBox.OQ.CTP.BrokerItem);
61 | //
62 | // listBoxServer
63 | //
64 | this.listBoxServer.DataSource = this.serverItemBindingSource;
65 | this.listBoxServer.DisplayMember = "Label";
66 | this.listBoxServer.FormattingEnabled = true;
67 | this.listBoxServer.Location = new System.Drawing.Point(289, 50);
68 | this.listBoxServer.Name = "listBoxServer";
69 | this.listBoxServer.Size = new System.Drawing.Size(216, 264);
70 | this.listBoxServer.TabIndex = 0;
71 | //
72 | // serverItemBindingSource
73 | //
74 | this.serverItemBindingSource.DataSource = typeof(QuantBox.OQ.CTP.ServerItem);
75 | //
76 | // buttonAdd
77 | //
78 | this.buttonAdd.Location = new System.Drawing.Point(234, 50);
79 | this.buttonAdd.Name = "buttonAdd";
80 | this.buttonAdd.Size = new System.Drawing.Size(49, 23);
81 | this.buttonAdd.TabIndex = 1;
82 | this.buttonAdd.Text = "=>";
83 | this.buttonAdd.UseVisualStyleBackColor = true;
84 | this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);
85 | //
86 | // buttonRemove
87 | //
88 | this.buttonRemove.Location = new System.Drawing.Point(234, 79);
89 | this.buttonRemove.Name = "buttonRemove";
90 | this.buttonRemove.Size = new System.Drawing.Size(49, 23);
91 | this.buttonRemove.TabIndex = 1;
92 | this.buttonRemove.Text = "<-";
93 | this.buttonRemove.UseVisualStyleBackColor = true;
94 | this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click);
95 | //
96 | // textBoxUrl
97 | //
98 | this.textBoxUrl.Location = new System.Drawing.Point(12, 12);
99 | this.textBoxUrl.Name = "textBoxUrl";
100 | this.textBoxUrl.Size = new System.Drawing.Size(412, 20);
101 | this.textBoxUrl.TabIndex = 2;
102 | this.textBoxUrl.Text = "https://raw.github.com/QuantBox/OpenQuant-CTP/master/CTP.Brokers.xml";
103 | //
104 | // buttonUpdate
105 | //
106 | this.buttonUpdate.Location = new System.Drawing.Point(430, 9);
107 | this.buttonUpdate.Name = "buttonUpdate";
108 | this.buttonUpdate.Size = new System.Drawing.Size(75, 23);
109 | this.buttonUpdate.TabIndex = 3;
110 | this.buttonUpdate.Text = "在线更新";
111 | this.buttonUpdate.UseVisualStyleBackColor = true;
112 | this.buttonUpdate.Click += new System.EventHandler(this.buttonUpdate_Click);
113 | //
114 | // ServersManagerForm
115 | //
116 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
117 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
118 | this.ClientSize = new System.Drawing.Size(519, 334);
119 | this.Controls.Add(this.buttonUpdate);
120 | this.Controls.Add(this.textBoxUrl);
121 | this.Controls.Add(this.buttonRemove);
122 | this.Controls.Add(this.buttonAdd);
123 | this.Controls.Add(this.listBoxServer);
124 | this.Controls.Add(this.listBoxBroker);
125 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
126 | this.Name = "ServersManagerForm";
127 | this.Text = "经纪商 - 服务器地址 列表";
128 | this.Load += new System.EventHandler(this.ServersManagerForm_Load);
129 | ((System.ComponentModel.ISupportInitialize)(this.brokerItemBindingSource)).EndInit();
130 | ((System.ComponentModel.ISupportInitialize)(this.serverItemBindingSource)).EndInit();
131 | this.ResumeLayout(false);
132 | this.PerformLayout();
133 |
134 | }
135 |
136 | #endregion
137 |
138 | private System.Windows.Forms.ListBox listBoxBroker;
139 | private System.Windows.Forms.ListBox listBoxServer;
140 | private System.Windows.Forms.Button buttonAdd;
141 | private System.Windows.Forms.Button buttonRemove;
142 | private System.Windows.Forms.BindingSource serverItemBindingSource;
143 | private System.Windows.Forms.BindingSource brokerItemBindingSource;
144 | private System.Windows.Forms.TextBox textBoxUrl;
145 | private System.Windows.Forms.Button buttonUpdate;
146 | }
147 | }
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/ServersManagerForm.cs:
--------------------------------------------------------------------------------
1 | using SmartQuant;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Data;
6 | using System.Drawing;
7 | using System.Linq;
8 | using System.Net;
9 | using System.Text;
10 | using System.Windows.Forms;
11 | using QuantBox.OQ.CTP;
12 |
13 | #if CTP
14 | namespace QuantBox.OQ.CTP
15 | #elif CTPZQ
16 | namespace QuantBox.OQ.CTPZQ
17 | #endif
18 | {
19 | public partial class ServersManagerForm : Form
20 | {
21 | private APIProvider provider;
22 | public void Init(APIProvider provider)
23 | {
24 | this.provider = provider;
25 |
26 | textBoxUrl.Text = string.Format(@"https://raw.github.com/QuantBox/OpenQuant-CTP/master/{0}.Brokers.xml", provider.Name);
27 | }
28 |
29 | public ServersManagerForm()
30 | {
31 | InitializeComponent();
32 | }
33 |
34 | private void ServersManagerForm_Load(object sender, EventArgs e)
35 | {
36 | provider.LoadBrokers();
37 |
38 | serverItemBindingSource.DataSource = provider.Server;
39 | brokerItemBindingSource.DataSource = provider.Brokers;
40 | }
41 |
42 | private void buttonRemove_Click(object sender, EventArgs e)
43 | {
44 | int nSel = listBoxServer.SelectedIndex;
45 | if (nSel >= 0)
46 | {
47 | provider.Server.RemoveAt(nSel);
48 | provider.SettingsChanged();
49 | }
50 | }
51 |
52 | private void buttonAdd_Click(object sender, EventArgs e)
53 | {
54 | int nSel = listBoxBroker.SelectedIndex;
55 | if (nSel >= 0)
56 | {
57 | BrokerItem bi = provider.Brokers[nSel];
58 | foreach(ServerItem si in bi.Server)
59 | {
60 | provider.Server.Add(si);
61 | }
62 | provider.SettingsChanged();
63 | }
64 | }
65 |
66 | private void buttonUpdate_Click(object sender, EventArgs e)
67 | {
68 | ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
69 |
70 | WebClient wc = new WebClient();
71 | try
72 | {
73 | buttonUpdate.Enabled = false;
74 |
75 | wc.DownloadFile(textBoxUrl.Text, provider.brokersFile);
76 |
77 | provider.LoadBrokers();
78 | brokerItemBindingSource.DataSource = provider.Brokers;
79 |
80 | MessageBox.Show("远程配置下载成功!");
81 | }
82 | catch (Exception ex)
83 | {
84 | MessageBox.Show(ex.Message);
85 | }
86 | finally
87 | {
88 | wc.Dispose();
89 | buttonUpdate.Enabled = true;
90 | }
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/ServersManagerForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 205, 17
122 |
123 |
124 | 17, 17
125 |
126 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/ServersManagerTypeEditor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing.Design;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Windows.Forms.Design;
8 |
9 | #if CTP
10 | namespace QuantBox.OQ.CTP
11 | #elif CTPZQ
12 | namespace QuantBox.OQ.CTPZQ
13 | #endif
14 | {
15 | class ServersManagerTypeEditor : UITypeEditor
16 | {
17 | // Methods
18 | public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
19 | {
20 | if (((context == null) || (context.Instance == null)) || (provider == null))
21 | {
22 | return base.EditValue(context, provider, value);
23 | }
24 | IWindowsFormsEditorService service = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
25 | if (service != null)
26 | {
27 | ServersManagerForm dialog = new ServersManagerForm();
28 | dialog.Init(context.Instance as APIProvider);
29 | service.ShowDialog(dialog);
30 | }
31 | return value;
32 | }
33 |
34 | public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
35 | {
36 | if ((context != null) && (context.Instance != null))
37 | {
38 | return UITypeEditorEditStyle.Modal;
39 | }
40 | return base.GetEditStyle(context);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/TraderApiWrapper.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using QuantBox.CSharp2CTP;
3 | using SmartQuant;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.IO;
7 | using System.Linq;
8 | using System.Text;
9 |
10 | namespace QuantBox.OQ.CTP
11 | {
12 | public class TraderApiWrapper:ApiWrapper
13 | {
14 | public fnOnErrRtnOrderAction _fnOnErrRtnOrderAction_Holder;
15 | public fnOnErrRtnOrderInsert _fnOnErrRtnOrderInsert_Holder;
16 | public fnOnRspOrderAction _fnOnRspOrderAction_Holder;
17 | public fnOnRspOrderInsert _fnOnRspOrderInsert_Holder;
18 | public fnOnRspQryDepthMarketData _fnOnRspQryDepthMarketData_Holder;
19 | public fnOnRspQryInstrument _fnOnRspQryInstrument_Holder;
20 | public fnOnRspQryInstrumentCommissionRate _fnOnRspQryInstrumentCommissionRate_Holder;
21 | public fnOnRspQryInvestorPosition _fnOnRspQryInvestorPosition_Holder;
22 | public fnOnRspQryTradingAccount _fnOnRspQryTradingAccount_Holder;
23 | public fnOnRtnInstrumentStatus _fnOnRtnInstrumentStatus_Holder;
24 | public fnOnRtnOrder _fnOnRtnOrder_Holder;
25 | public fnOnRtnTrade _fnOnRtnTrade_Holder;
26 |
27 | #if CTP
28 | public fnOnRspQryInstrumentMarginRate _fnOnRspQryInstrumentMarginRate_Holder;
29 | #endif
30 |
31 | private THOST_TE_RESUME_TYPE ResumeType;
32 |
33 | public void Connect(ServerItem server, AccountItem account,THOST_TE_RESUME_TYPE resumeType)
34 | {
35 | tempPath = Framework.Installation.TempDir.FullName + Path.DirectorySeparatorChar + server.BrokerID + Path.DirectorySeparatorChar + account.InvestorId;
36 | Directory.CreateDirectory(tempPath);
37 | ResumeType = resumeType;
38 |
39 | Disconnect_TD();
40 |
41 | Connect_MsgQueue();
42 | Connect_TD();
43 | }
44 |
45 | public void Disconnect()
46 | {
47 | Disconnect_TD();
48 | Disconnect_MsgQueue();
49 | }
50 |
51 | //建立交易
52 | private void Connect_TD()
53 | {
54 | lock (_lock)
55 | {
56 | if (null == Api || IntPtr.Zero == Api)
57 | {
58 | Api = TraderApi.TD_CreateTdApi();
59 | TraderApi.CTP_RegOnErrRtnOrderAction(m_pMsgQueue, _fnOnErrRtnOrderAction_Holder);
60 | TraderApi.CTP_RegOnErrRtnOrderInsert(m_pMsgQueue, _fnOnErrRtnOrderInsert_Holder);
61 | TraderApi.CTP_RegOnRspOrderAction(m_pMsgQueue, _fnOnRspOrderAction_Holder);
62 | TraderApi.CTP_RegOnRspOrderInsert(m_pMsgQueue, _fnOnRspOrderInsert_Holder);
63 | TraderApi.CTP_RegOnRspQryDepthMarketData(m_pMsgQueue, _fnOnRspQryDepthMarketData_Holder);
64 | TraderApi.CTP_RegOnRspQryInstrument(m_pMsgQueue, _fnOnRspQryInstrument_Holder);
65 | TraderApi.CTP_RegOnRspQryInstrumentCommissionRate(m_pMsgQueue, _fnOnRspQryInstrumentCommissionRate_Holder);
66 | TraderApi.CTP_RegOnRspQryInvestorPosition(m_pMsgQueue, _fnOnRspQryInvestorPosition_Holder);
67 | TraderApi.CTP_RegOnRspQryTradingAccount(m_pMsgQueue, _fnOnRspQryTradingAccount_Holder);
68 | TraderApi.CTP_RegOnRtnInstrumentStatus(m_pMsgQueue, _fnOnRtnInstrumentStatus_Holder);
69 | TraderApi.CTP_RegOnRtnOrder(m_pMsgQueue, _fnOnRtnOrder_Holder);
70 | TraderApi.CTP_RegOnRtnTrade(m_pMsgQueue, _fnOnRtnTrade_Holder);
71 | #if CTP
72 | TraderApi.CTP_RegOnRspQryInstrumentMarginRate(m_pMsgQueue, _fnOnRspQryInstrumentMarginRate_Holder);
73 | #endif
74 | TraderApi.TD_RegMsgQueue2TdApi(Api, m_pMsgQueue);
75 | TraderApi.TD_Connect(Api, tempPath, string.Join(";", server.Trading.ToArray()),
76 | server.BrokerID, account.InvestorId, account.Password,
77 | ResumeType,
78 | server.UserProductInfo, server.AuthCode);
79 |
80 | //向单例对象中注入操作用句柄
81 | //CTPAPI.GetInstance().__RegTdApi(m_pTdApi);
82 | }
83 | }
84 | }
85 |
86 | private void Disconnect_TD()
87 | {
88 | lock (_lock)
89 | {
90 | if (null != Api && IntPtr.Zero != Api)
91 | {
92 | TraderApi.TD_RegMsgQueue2TdApi(Api, IntPtr.Zero);
93 | TraderApi.TD_ReleaseTdApi(Api);
94 | Api = IntPtr.Zero;
95 |
96 | //CTPAPI.GetInstance().__RegTdApi(m_pTdApi);
97 | }
98 | IsConnected = false;
99 | }
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/QuantBox.OQ.CTP/WinAPI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | #if CTP
5 | namespace QuantBox.OQ.CTP
6 | #elif CTPZQ
7 | namespace QuantBox.OQ.CTPZQ
8 | #endif
9 | {
10 | class WinAPI
11 | {
12 | //imports SetLocalTime function from kernel32.dll
13 | [DllImport("kernel32.dll", SetLastError = true)]
14 | public static extern int SetLocalTime(ref SystemTime lpSystemTime);
15 |
16 | //struct for date/time apis
17 | [StructLayout(LayoutKind.Sequential)]
18 | public struct SystemTime
19 | {
20 | public short wYear;
21 | public short wMonth;
22 | public short wDayOfWeek;
23 | public short wDay;
24 | public short wHour;
25 | public short wMinute;
26 | public short wSecond;
27 | public short wMilliseconds;
28 | }
29 |
30 | public static int SetLocalTime(DateTime datetime)
31 | {
32 | SystemTime systNew = new SystemTime();
33 |
34 | // 设置属性
35 | systNew.wDay = (short)datetime.Day;
36 | systNew.wMonth = (short)datetime.Month;
37 | systNew.wYear = (short)datetime.Year;
38 | systNew.wHour = (short)datetime.Hour;
39 | systNew.wMinute = (short)datetime.Minute;
40 | systNew.wSecond = (short)datetime.Second;
41 | systNew.wMilliseconds = (short)datetime.Millisecond;
42 |
43 | // 调用API,更新系统时间
44 | return SetLocalTime(ref systNew);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------