├── .gitattributes
├── .gitignore
├── ArchiveData
├── App.config
├── ArchiveData.csproj
├── CommandLine.cs
├── H5DataWriter.cs
├── PbTickStruct.cs
├── Pd0DataReader.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── DataDownload
├── App.config
├── DataDownload.cs
├── DataDownload.csproj
├── PathHelper.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── DataReceiver
├── ApiBase.cs
├── App.config
├── DRTickWriter.cs
├── DataReceiver.cs
├── DataReceiver.csproj
├── KdbWriter.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Struct.cs
├── WatcherTimer.cs
├── XAPI_Extensions.cs
├── c.cs
└── packages.config
├── DataReceiver使用手册.docx
├── GetInstruments
├── App.config
├── GetInstruments.cs
├── GetInstruments.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── QuantBox.DataReceiver.sln
├── README.md
├── clear.bat
├── demo
├── read_hdf5.m
├── read_hdf5.py
└── test.h5
├── lib
├── QuantBox.Data.Serializer.dll
├── XAPI_CSharp.exe
└── protobuf-net.dll
├── php.zip
└── test.zip
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # Build results
11 | [Dd]ebug/
12 | [Dd]ebugPublic/
13 | [Rr]elease/
14 | [Rr]eleases/
15 | x64/
16 | x86/
17 | build/
18 | bld/
19 | [Bb]in/
20 | [Oo]bj/
21 |
22 | # Roslyn cache directories
23 | *.ide/
24 |
25 | # MSTest test Results
26 | [Tt]est[Rr]esult*/
27 | [Bb]uild[Ll]og.*
28 |
29 | #NUNIT
30 | *.VisualState.xml
31 | TestResult.xml
32 |
33 | # Build Results of an ATL Project
34 | [Dd]ebugPS/
35 | [Rr]eleasePS/
36 | dlldata.c
37 |
38 | *_i.c
39 | *_p.c
40 | *_i.h
41 | *.ilk
42 | *.meta
43 | *.obj
44 | *.pch
45 | *.pdb
46 | *.pgc
47 | *.pgd
48 | *.rsp
49 | *.sbr
50 | *.tlb
51 | *.tli
52 | *.tlh
53 | *.tmp
54 | *.tmp_proj
55 | *.log
56 | *.vspscc
57 | *.vssscc
58 | .builds
59 | *.pidb
60 | *.svclog
61 | *.scc
62 |
63 | # Chutzpah Test files
64 | _Chutzpah*
65 |
66 | # Visual C++ cache files
67 | ipch/
68 | *.aps
69 | *.ncb
70 | *.opensdf
71 | *.sdf
72 | *.cachefile
73 |
74 | # Visual Studio profiler
75 | *.psess
76 | *.vsp
77 | *.vspx
78 |
79 | # TFS 2012 Local Workspace
80 | $tf/
81 |
82 | # Guidance Automation Toolkit
83 | *.gpState
84 |
85 | # ReSharper is a .NET coding add-in
86 | _ReSharper*/
87 | *.[Rr]e[Ss]harper
88 | *.DotSettings.user
89 |
90 | # JustCode is a .NET coding addin-in
91 | .JustCode
92 |
93 | # TeamCity is a build add-in
94 | _TeamCity*
95 |
96 | # DotCover is a Code Coverage Tool
97 | *.dotCover
98 |
99 | # NCrunch
100 | _NCrunch_*
101 | .*crunch*.local.xml
102 |
103 | # MightyMoose
104 | *.mm.*
105 | AutoTest.Net/
106 |
107 | # Web workbench (sass)
108 | .sass-cache/
109 |
110 | # Installshield output folder
111 | [Ee]xpress/
112 |
113 | # DocProject is a documentation generator add-in
114 | DocProject/buildhelp/
115 | DocProject/Help/*.HxT
116 | DocProject/Help/*.HxC
117 | DocProject/Help/*.hhc
118 | DocProject/Help/*.hhk
119 | DocProject/Help/*.hhp
120 | DocProject/Help/Html2
121 | DocProject/Help/html
122 |
123 | # Click-Once directory
124 | publish/
125 |
126 | # Publish Web Output
127 | *.[Pp]ublish.xml
128 | *.azurePubxml
129 | # TODO: Comment the next line if you want to checkin your web deploy settings
130 | # but database connection strings (with potential passwords) will be unencrypted
131 | *.pubxml
132 | *.publishproj
133 |
134 | # NuGet Packages
135 | *.nupkg
136 | # The packages folder can be ignored because of Package Restore
137 | **/packages/*
138 | # except build/, which is used as an MSBuild target.
139 | !**/packages/build/
140 | # If using the old MSBuild-Integrated Package Restore, uncomment this:
141 | #!**/packages/repositories.config
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
186 | # =========================
187 | # Operating System Files
188 | # =========================
189 |
190 | # OSX
191 | # =========================
192 |
193 | .DS_Store
194 | .AppleDouble
195 | .LSOverride
196 |
197 | # Thumbnails
198 | ._*
199 |
200 | # Files that might appear on external disk
201 | .Spotlight-V100
202 | .Trashes
203 |
204 | # Directories potentially created on remote AFP share
205 | .AppleDB
206 | .AppleDesktop
207 | Network Trash Folder
208 | Temporary Items
209 | .apdisk
210 |
211 | # Windows
212 | # =========================
213 |
214 | # Windows image file caches
215 | Thumbs.db
216 | ehthumbs.db
217 |
218 | # Folder config file
219 | Desktop.ini
220 |
221 | # Recycle Bin used on file shares
222 | $RECYCLE.BIN/
223 |
224 | # Windows Installer files
225 | *.cab
226 | *.msi
227 | *.msm
228 | *.msp
229 |
230 | # Windows shortcuts
231 | *.lnk
232 |
--------------------------------------------------------------------------------
/ArchiveData/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/ArchiveData/ArchiveData.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C03DE914-AB11-4FE3-B44F-DF2260280561}
8 | Exe
9 | Properties
10 | ArchiveData
11 | ArchiveData
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | ..\bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | ..\packages\HDF.PInvoke.1.10.1.0\lib\HDF.PInvoke.dll
37 |
38 |
39 | ..\packages\NLog.4.4.12\lib\net45\NLog.dll
40 |
41 |
42 | False
43 | ..\lib\QuantBox.Data.Serializer.dll
44 |
45 |
46 | ..\packages\SevenZipSharp.0.64\lib\SevenZipSharp.dll
47 | True
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | {529aac14-b1ff-4524-929d-40756cab260b}
73 | DataDownload
74 |
75 |
76 |
77 |
78 |
79 | if not exist "$(TargetDir)bin32" md "$(TargetDir)bin32"
80 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin32\*.*" "$(TargetDir)bin32"
81 | if not exist "$(TargetDir)bin64" md "$(TargetDir)bin64"
82 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin64\*.*" "$(TargetDir)bin64"
83 |
84 |
91 |
--------------------------------------------------------------------------------
/ArchiveData/CommandLine.cs:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------
2 | /// Simple CommandLine Parser
3 | /// Copyright (C) 2008 Chris Stoy
4 | /// For questions or comments see the article on CodeProject (www.codeproject.com)
5 | /// or email me at cstoy at nc.rr.com.
6 | ///
7 | /// You are free to use this code in all commercial and non-commercial applications
8 | /// as long as this copyright message is left intact.
9 | /// Use this code at your own risk. I take no responsibility if it should fail to
10 | /// do anything you would expect it to do and it could, at any time, fail to function
11 | /// in any manner. You have the source code, make it do what you want.
12 | //---------------------------------------------------------------------
13 | using System;
14 | using System.Collections.Generic;
15 | using System.Text;
16 |
17 | //---------------------------------------------------------------------
18 | namespace Utility
19 | {
20 | //---------------------------------------------------------------------
21 | ///
22 | /// Contains the parsed command line arguments. This consists of two
23 | /// lists, one of argument pairs, and one of stand-alone arguments.
24 | ///
25 | public class CommandArgs
26 | {
27 | //---------------------------------------------------------------------
28 | ///
29 | /// Returns the dictionary of argument/value pairs.
30 | ///
31 | public Dictionary ArgPairs
32 | {
33 | get { return mArgPairs; }
34 | }
35 | Dictionary mArgPairs = new Dictionary();
36 |
37 | //---------------------------------------------------------------------
38 | ///
39 | /// Returns the list of stand-alone parameters.
40 | ///
41 | public List Params
42 | {
43 | get { return mParams; }
44 | }
45 | List mParams = new List();
46 | }
47 |
48 | //---------------------------------------------------------------------
49 | ///
50 | /// Implements command line parsing
51 | ///
52 | public class CommandLine
53 | {
54 | //---------------------------------------------------------------------
55 | ///
56 | /// Parses the passed command line arguments and returns the result
57 | /// in a CommandArgs object.
58 | ///
59 | /// The command line is assumed to be in the format:
60 | ///
61 | /// CMD [param] [[-|--|\]<arg>[[=]<value>]] [param]
62 | ///
63 | /// Basically, stand-alone parameters can appear anywhere on the command line.
64 | /// Arguments are defined as key/value pairs. The argument key must begin
65 | /// with a '-', '--', or '\'. Between the argument and the value must be at
66 | /// least one space or a single '='. Extra spaces are ignored. Arguments MAY
67 | /// be followed by a value or, if no value supplied, the string 'true' is used.
68 | /// You must enclose argument values in quotes if they contain a space, otherwise
69 | /// they will not parse correctly.
70 | ///
71 | /// Example command lines are:
72 | ///
73 | /// cmd first -o outfile.txt --compile second \errors=errors.txt third fourth --test = "the value" fifth
74 | ///
75 | /// array of command line arguments
76 | /// CommandArgs object containing the parsed command line
77 | public static CommandArgs Parse(string[] args)
78 | {
79 | char[] kEqual = new char[] { '=' };
80 | char[] kArgStart = new char[] { '-', '\\' };
81 |
82 | CommandArgs ca = new CommandArgs();
83 | int ii = -1;
84 | string token = NextToken( args, ref ii );
85 | while ( token != null )
86 | {
87 | if (IsArg(token))
88 | {
89 | string arg = token.TrimStart(kArgStart).TrimEnd(kEqual);
90 |
91 | string value = null;
92 |
93 | if (arg.Contains("="))
94 | {
95 | // arg was specified with an '=' sign, so we need
96 | // to split the string into the arg and value, but only
97 | // if there is no space between the '=' and the arg and value.
98 | string[] r = arg.Split(kEqual, 2);
99 | if ( r.Length == 2 && r[1] != string.Empty)
100 | {
101 | arg = r[0];
102 | value = r[1];
103 | }
104 | }
105 |
106 | while ( value == null )
107 | {
108 | string next = NextToken(args, ref ii);
109 | if (next != null)
110 | {
111 | if (IsArg(next))
112 | {
113 | // push the token back onto the stack so
114 | // it gets picked up on next pass as an Arg
115 | ii--;
116 | value = "true";
117 | }
118 | else if (next != "=")
119 | {
120 | // save the value (trimming any '=' from the start)
121 | value = next.TrimStart(kEqual);
122 | }
123 | }
124 | }
125 |
126 | // save the pair
127 | ca.ArgPairs.Add(arg, value);
128 | }
129 | else if (token != string.Empty)
130 | {
131 | // this is a stand-alone parameter.
132 | ca.Params.Add(token);
133 | }
134 |
135 | token = NextToken(args, ref ii);
136 | }
137 |
138 | return ca;
139 | }
140 |
141 | //---------------------------------------------------------------------
142 | ///
143 | /// Returns True if the passed string is an argument (starts with
144 | /// '-', '--', or '\'.)
145 | ///
146 | /// the string token to test
147 | /// true if the passed string is an argument, else false if a parameter
148 | static bool IsArg(string arg)
149 | {
150 | return (arg.StartsWith("-") || arg.StartsWith("\\"));
151 | }
152 |
153 | //---------------------------------------------------------------------
154 | ///
155 | /// Returns the next string token in the argument list
156 | ///
157 | /// list of string tokens
158 | /// index of the current token in the array
159 | /// the next string token, or null if no more tokens in array
160 | static string NextToken(string[] args, ref int ii)
161 | {
162 | ii++; // move to next token
163 | while ( ii < args.Length )
164 | {
165 | string cur = args[ii].Trim();
166 | if (cur != string.Empty)
167 | {
168 | // found valid token
169 | return cur;
170 | }
171 | ii++;
172 | }
173 |
174 | // failed to get another token
175 | return null;
176 | }
177 |
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/ArchiveData/H5DataWriter.cs:
--------------------------------------------------------------------------------
1 | using HDF.PInvoke;
2 | using QuantBox.Data.Serializer.V2;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace ArchiveData
11 | {
12 | public class H5DataWriter
13 | {
14 | private long h5;
15 |
16 | public void Open(string OutputFile)
17 | {
18 | h5 = H5F.create(OutputFile, H5F.ACC_TRUNC, H5P.DEFAULT, H5P.DEFAULT);
19 | }
20 |
21 | public void Close()
22 | {
23 | H5F.close(h5);
24 | }
25 |
26 | public void Writer(List list,string dataset_name)
27 | {
28 | var t = typeof(PbTickStruct5);
29 | var size = Marshal.SizeOf(t);
30 |
31 | var typeId = create_type();
32 |
33 | // chunk一定得小于dim数据量,多了会出错
34 | // 如果数据100条左右,按
35 | var log10 = (int)Math.Log10(list.Count);
36 | ulong pow = (ulong)Math.Pow(10, log10);
37 | ulong c_s = Math.Min(1000, pow);
38 | ulong[] chunk_size = new ulong[] { c_s };
39 |
40 | ulong[] dims = new ulong[] { (ulong)list.Count };
41 |
42 | long dcpl = 0;
43 | if (list.Count == 0 || log10 == 0)
44 | { }
45 | else
46 | {
47 | dcpl = create_property(chunk_size);
48 | }
49 |
50 | var spaceid = H5S.create_simple(dims.Length, dims, null);
51 | var datasetid = H5D.create(h5, dataset_name, typeId, spaceid, H5P.DEFAULT, dcpl);
52 |
53 | IntPtr p = Marshal.AllocHGlobal(size * (int)dims[0]);
54 |
55 | int i = 0;
56 | foreach (var b in list)
57 | {
58 | var s = DataConvert.toStruct(b);
59 | Marshal.StructureToPtr(s, new IntPtr(p.ToInt32() + size * i), false);
60 | ++i;
61 | }
62 |
63 | H5D.write(datasetid, typeId, spaceid, H5S.ALL, H5P.DEFAULT, p);
64 |
65 | H5D.close(datasetid);
66 | H5S.close(spaceid);
67 | H5T.close(typeId);
68 | H5P.close(dcpl);
69 |
70 |
71 | Marshal.FreeHGlobal(p);
72 | }
73 |
74 | private long create_type()
75 | {
76 | var t = typeof(PbTickStruct5);
77 | var size = Marshal.SizeOf(t);
78 | var float_size = Marshal.SizeOf(typeof(float));
79 | var int_size = Marshal.SizeOf(typeof(int));
80 |
81 | var typeId = H5T.create(H5T.class_t.COMPOUND, new IntPtr(size));
82 |
83 |
84 | H5T.insert(typeId, "TradingDay", Marshal.OffsetOf(t, "TradingDay"), H5T.NATIVE_INT32);
85 | H5T.insert(typeId, "ActionDay", Marshal.OffsetOf(t, "ActionDay"), H5T.NATIVE_INT32);
86 | H5T.insert(typeId, "UpdateTime", Marshal.OffsetOf(t, "UpdateTime"), H5T.NATIVE_INT32);
87 | H5T.insert(typeId, "UpdateMillisec", Marshal.OffsetOf(t, "UpdateMillisec"), H5T.NATIVE_INT32);
88 |
89 | var Symbol_type = H5T.copy(H5T.C_S1);
90 | H5T.set_size(Symbol_type, new IntPtr(64));
91 | var Exchange_type = H5T.copy(H5T.C_S1);
92 | H5T.set_size(Exchange_type, new IntPtr(9));
93 | H5T.insert(typeId, "Symbol", Marshal.OffsetOf(t, "Symbol"), Symbol_type);
94 | H5T.insert(typeId, "Exchange", Marshal.OffsetOf(t, "Exchange"), Exchange_type);
95 |
96 | H5T.insert(typeId, "LastPrice", Marshal.OffsetOf(t, "LastPrice"), H5T.NATIVE_FLOAT);
97 | H5T.insert(typeId, "Volume", Marshal.OffsetOf(t, "Volume"), H5T.NATIVE_FLOAT);
98 | H5T.insert(typeId, "Turnover", Marshal.OffsetOf(t, "Turnover"), H5T.NATIVE_FLOAT);
99 | H5T.insert(typeId, "OpenInterest", Marshal.OffsetOf(t, "OpenInterest"), H5T.NATIVE_FLOAT);
100 | H5T.insert(typeId, "AveragePrice", Marshal.OffsetOf(t, "AveragePrice"), H5T.NATIVE_FLOAT);
101 | H5T.insert(typeId, "OpenPrice", Marshal.OffsetOf(t, "OpenPrice"), H5T.NATIVE_FLOAT);
102 | H5T.insert(typeId, "HighestPrice", Marshal.OffsetOf(t, "HighestPrice"), H5T.NATIVE_FLOAT);
103 | H5T.insert(typeId, "LowestPrice", Marshal.OffsetOf(t, "LowestPrice"), H5T.NATIVE_FLOAT);
104 | H5T.insert(typeId, "ClosePrice", Marshal.OffsetOf(t, "ClosePrice"), H5T.NATIVE_FLOAT);
105 | H5T.insert(typeId, "SettlementPrice", Marshal.OffsetOf(t, "SettlementPrice"), H5T.NATIVE_FLOAT);
106 | H5T.insert(typeId, "UpperLimitPrice", Marshal.OffsetOf(t, "UpperLimitPrice"), H5T.NATIVE_FLOAT);
107 | H5T.insert(typeId, "LowerLimitPrice", Marshal.OffsetOf(t, "LowerLimitPrice"), H5T.NATIVE_FLOAT);
108 | H5T.insert(typeId, "PreClosePrice", Marshal.OffsetOf(t, "PreClosePrice"), H5T.NATIVE_FLOAT);
109 | H5T.insert(typeId, "PreSettlementPrice", Marshal.OffsetOf(t, "PreSettlementPrice"), H5T.NATIVE_FLOAT);
110 | H5T.insert(typeId, "PreOpenInterest", Marshal.OffsetOf(t, "PreOpenInterest"), H5T.NATIVE_FLOAT);
111 |
112 | var price_intptr = Marshal.OffsetOf(t, "Price");
113 | H5T.insert(typeId, "BidPrice5", price_intptr + float_size * 0, H5T.NATIVE_FLOAT);
114 | H5T.insert(typeId, "BidPrice4", price_intptr + float_size * 1, H5T.NATIVE_FLOAT);
115 | H5T.insert(typeId, "BidPrice3", price_intptr + float_size * 2, H5T.NATIVE_FLOAT);
116 | H5T.insert(typeId, "BidPrice2", price_intptr + float_size * 3, H5T.NATIVE_FLOAT);
117 | H5T.insert(typeId, "BidPrice1", price_intptr + float_size * 4, H5T.NATIVE_FLOAT);
118 | H5T.insert(typeId, "AskPrice1", price_intptr + float_size * 5, H5T.NATIVE_FLOAT);
119 | H5T.insert(typeId, "AskPrice2", price_intptr + float_size * 6, H5T.NATIVE_FLOAT);
120 | H5T.insert(typeId, "AskPrice3", price_intptr + float_size * 7, H5T.NATIVE_FLOAT);
121 | H5T.insert(typeId, "AskPrice4", price_intptr + float_size * 8, H5T.NATIVE_FLOAT);
122 | H5T.insert(typeId, "AskPrice5", price_intptr + float_size * 9, H5T.NATIVE_FLOAT);
123 |
124 | var size_intptr = Marshal.OffsetOf(t, "Size");
125 | H5T.insert(typeId, "BidSize5", size_intptr + int_size * 0, H5T.NATIVE_INT32);
126 | H5T.insert(typeId, "BidSize4", size_intptr + int_size * 1, H5T.NATIVE_INT32);
127 | H5T.insert(typeId, "BidSize3", size_intptr + int_size * 2, H5T.NATIVE_INT32);
128 | H5T.insert(typeId, "BidSize2", size_intptr + int_size * 3, H5T.NATIVE_INT32);
129 | H5T.insert(typeId, "BidSize1", size_intptr + int_size * 4, H5T.NATIVE_INT32);
130 | H5T.insert(typeId, "AskSize1", size_intptr + int_size * 5, H5T.NATIVE_INT32);
131 | H5T.insert(typeId, "AskSize2", size_intptr + int_size * 6, H5T.NATIVE_INT32);
132 | H5T.insert(typeId, "AskSize3", size_intptr + int_size * 7, H5T.NATIVE_INT32);
133 | H5T.insert(typeId, "AskSize4", size_intptr + int_size * 8, H5T.NATIVE_INT32);
134 | H5T.insert(typeId, "AskSize5", size_intptr + int_size * 9, H5T.NATIVE_INT32);
135 |
136 | return typeId;
137 | }
138 |
139 | private long create_property(ulong[] chunk_size)
140 | {
141 | var dcpl = H5P.create(H5P.DATASET_CREATE);
142 | H5P.set_layout(dcpl, H5D.layout_t.CHUNKED);
143 | H5P.set_chunk(dcpl, chunk_size.Length, chunk_size);
144 | H5P.set_deflate(dcpl, 6);
145 | return dcpl;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/ArchiveData/PbTickStruct.cs:
--------------------------------------------------------------------------------
1 | using QuantBox.Data.Serializer.V2;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace ArchiveData
10 | {
11 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
12 | public struct PbTickStruct5
13 | {
14 | public int TradingDay;
15 | public int ActionDay;
16 | public int UpdateTime;
17 | public int UpdateMillisec;
18 |
19 | ///
20 | /// 合约代码
21 | ///
22 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
23 | public string Symbol;
24 | ///
25 | /// 交易所代码
26 | ///
27 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
28 | public string Exchange;
29 |
30 | ///
31 | /// 最新价
32 | ///
33 | public float LastPrice;
34 | ///
35 | /// 数量
36 | ///
37 | public float Volume;
38 | ///
39 | /// 成交金额
40 | ///
41 | public float Turnover;
42 | ///
43 | /// 持仓量
44 | ///
45 | public float OpenInterest;
46 | ///
47 | /// 当日均价
48 | ///
49 | public float AveragePrice;
50 |
51 |
52 | ///
53 | /// 今开盘
54 | ///
55 | public float OpenPrice;
56 | ///
57 | /// 最高价
58 | ///
59 | public float HighestPrice;
60 | ///
61 | /// 最低价
62 | ///
63 | public float LowestPrice;
64 | ///
65 | /// 今收盘
66 | ///
67 | public float ClosePrice;
68 | ///
69 | /// 本次结算价
70 | ///
71 | public float SettlementPrice;
72 |
73 | ///
74 | /// 涨停板价
75 | ///
76 | public float UpperLimitPrice;
77 | ///
78 | /// 跌停板价
79 | ///
80 | public float LowerLimitPrice;
81 | ///
82 | /// 昨收盘
83 | ///
84 | public float PreClosePrice;
85 | ///
86 | /// 上次结算价
87 | ///
88 | public float PreSettlementPrice;
89 | ///
90 | /// 昨持仓量
91 | ///
92 | public float PreOpenInterest;
93 |
94 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
95 | public float[] Price;
96 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
97 | public int[] Size;
98 | }
99 |
100 | public class DataConvert
101 | {
102 | static PbTickCodec codec = new PbTickCodec();
103 |
104 | public static PbTickStruct5 toStruct(PbTickView input)
105 | {
106 | var o = default(PbTickStruct5);
107 |
108 | codec.GetUpdateTime(input,out o.UpdateTime,out o.UpdateMillisec);
109 |
110 | o.TradingDay = input.TradingDay;
111 | o.ActionDay = input.ActionDay;
112 | o.LastPrice = (float)input.LastPrice;
113 | o.Volume = input.Volume;
114 |
115 | o.Turnover = (float)input.Turnover;
116 | o.OpenInterest = (float)input.OpenInterest;
117 | o.AveragePrice = (float)input.AveragePrice;
118 |
119 | if (input.Bar != null)
120 | {
121 | o.OpenPrice = (float)input.Bar.Open;
122 | o.HighestPrice = (float)input.Bar.High;
123 | o.LowestPrice = (float)input.Bar.Low;
124 | o.ClosePrice = (float)input.Bar.Close;
125 | }
126 |
127 | if (input.Static != null)
128 | {
129 | o.LowerLimitPrice = (float)input.Static.LowerLimitPrice;
130 | o.UpperLimitPrice = (float)input.Static.UpperLimitPrice;
131 | o.SettlementPrice = (float)input.Static.SettlementPrice;
132 | o.Symbol = input.Static.Symbol;
133 | o.Exchange = input.Static.Exchange;
134 | //o.Symbol = "IF";
135 | //o.Exchange = "CFFEX";
136 | o.PreClosePrice = (float)input.Static.PreClosePrice;
137 | o.PreSettlementPrice = (float)input.Static.PreSettlementPrice;
138 | o.PreOpenInterest = input.Static.PreOpenInterest;
139 | }
140 |
141 | o.Price = new float[10];
142 | o.Size = new int[10];
143 |
144 | int count = input.DepthList == null ? 0 : input.DepthList.Count;
145 | if (count > 0)
146 | {
147 | int AskPos = DepthListHelper.FindAsk1Position(input.DepthList, input.AskPrice1); // 卖一位置
148 | int BidPos = AskPos - 1; // 买一位置,在数组中的位置
149 | int BidCount = BidPos + 1;
150 | int AskCount = count - AskPos;
151 |
152 |
153 | if (BidCount > 0)
154 | {
155 | int j = 0;
156 | for (int i = BidPos; i >= 0; --i)
157 | {
158 | o.Price[4 - j] = (float)input.DepthList[i].Price;
159 | o.Size[4 - j] = input.DepthList[i].Size;
160 |
161 | ++j;
162 | }
163 | }
164 |
165 | if (AskCount > 0)
166 | {
167 | int j = 0;
168 | for (int i = AskPos; i < count; ++i)
169 | {
170 | o.Price[5 + j] = (float)input.DepthList[i].Price;
171 | o.Size[5 + j] = input.DepthList[i].Size;
172 |
173 | ++j;
174 | }
175 | }
176 | }
177 |
178 | return o;
179 | }
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/ArchiveData/Pd0DataReader.cs:
--------------------------------------------------------------------------------
1 | using QuantBox.Data.Serializer.V2;
2 | using SevenZip;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace ArchiveData
11 | {
12 | public class Pd0DataReader
13 | {
14 | public QuantBox.Data.Serializer.PbTickSerializer Serializer = new QuantBox.Data.Serializer.PbTickSerializer();
15 |
16 | public List ReadOneFile(FileInfo file)
17 | {
18 | Stream _stream = new MemoryStream();
19 | var fileStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
20 | {
21 | try
22 | {
23 | using (var zip = new SevenZipExtractor(fileStream))
24 | {
25 | zip.ExtractFile(0, _stream);
26 | _stream.Seek(0, SeekOrigin.Begin);
27 | }
28 | }
29 | catch (Exception ex)
30 | {
31 | _stream = fileStream;
32 | try
33 | {
34 | // 有部分文件会出现zip的密码错误,然后把流关闭了,所以需要重新打开一次
35 | // 如果是写部分不会出问题,读的部分可能出问题
36 | _stream.Seek(0, SeekOrigin.Begin);
37 | }
38 | catch(Exception ex2)
39 | {
40 | _stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
41 | }
42 | }
43 | }
44 | return Serializer.Read2View(_stream);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/ArchiveData/Program.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using QuantBox.Data.Serializer.V2;
3 | using SevenZip;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Configuration;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Text.RegularExpressions;
11 | using System.Threading.Tasks;
12 | using Utility;
13 |
14 | namespace ArchiveData
15 | {
16 | class Program
17 | {
18 | public const string KEY_DataPath = "DataPath";
19 | public const string KEY_OutputPath_TradingDay = "OutputPath_TradingDay";
20 | public const string KEY_OutputPath_Instrument = "OutputPath_Instrument";
21 | public const string KEY_DefaultExchange = "DefaultExchange";
22 | public const string KEY_SevenZipExePath = "SevenZipExePath";
23 |
24 | public const string KEY_HDF5_TradingDay = "HDF5_TradingDay";
25 |
26 | public const string KEY_Clear_DataPath = "Clear_DataPath";
27 | public const string KEY_Clear_OutputPath_TradingDay = "Clear_OutputPath_TradingDay";
28 |
29 |
30 | static void HDF5_Convert(string target, string directory, Logger Log)
31 | {
32 | var dr = new Pd0DataReader();
33 | var files = new DirectoryInfo(directory).GetFiles("*", SearchOption.AllDirectories);
34 |
35 | int i = 0;
36 |
37 | var h5 = new H5DataWriter();
38 | h5.Open(target);
39 | foreach (var f in files)
40 | {
41 | var list = dr.ReadOneFile(f);
42 | string dataset_name = f.Name;
43 | string extension = f.Extension;
44 | if(!string.IsNullOrEmpty(extension))
45 | dataset_name = dataset_name.Replace(extension, "");
46 | Log.Info("开始写入表:{0}",dataset_name);
47 | h5.Writer(list, dataset_name);
48 |
49 | //if (i > 5)
50 | // break;
51 | ++i;
52 | }
53 | h5.Close();
54 | }
55 |
56 | static void Main(string[] args)
57 | {
58 | CommandArgs commandArgs = CommandLine.Parse(args);
59 |
60 | // 遍历,某个目录
61 | Logger Log = LogManager.GetCurrentClassLogger();
62 | //HDF5_Convert(@"D:\test.h5", @"D:\Users\Kan\Documents\GitHub\QuantBox.DataReceiver\bin\Debug\IF1509", Log);
63 | //return;
64 |
65 | string DataPath = ConfigurationManager.AppSettings[KEY_DataPath];
66 | string OutputPath_TradingDay = ConfigurationManager.AppSettings[KEY_OutputPath_TradingDay];
67 | string OutputPath_Instrument = ConfigurationManager.AppSettings[KEY_OutputPath_Instrument];
68 | string DefaultExchange = ConfigurationManager.AppSettings[KEY_DefaultExchange];
69 | string SevenZipExePath = ConfigurationManager.AppSettings[KEY_SevenZipExePath];
70 | bool Clear_DataPath = bool.Parse(commandArgs.ArgPairs.ContainsKey(KEY_Clear_DataPath) ? commandArgs.ArgPairs[KEY_Clear_DataPath] : ConfigurationManager.AppSettings[KEY_Clear_DataPath]);
71 | bool Clear_OutputPath_TradingDay = bool.Parse(commandArgs.ArgPairs.ContainsKey(KEY_Clear_OutputPath_TradingDay) ? commandArgs.ArgPairs[KEY_Clear_OutputPath_TradingDay] : ConfigurationManager.AppSettings[KEY_Clear_OutputPath_TradingDay]);
72 |
73 | //string HDF5_TradingDay = ConfigurationManager.AppSettings[KEY_HDF5_TradingDay];
74 |
75 |
76 | HashSet Set_TradingDay = new HashSet();
77 |
78 | // 遍历源数据目录下的所有文件
79 | var files = new DirectoryInfo(DataPath).GetFiles("*", SearchOption.AllDirectories);
80 | foreach (var f in files)
81 | {
82 | string exchange = string.Empty;
83 | string product = string.Empty;
84 | string instrument = string.Empty;
85 | string symbol = string.Empty;
86 | string date = string.Empty;
87 |
88 | // 解析文件名
89 | if (PathHelper.SplitFileName(f.Name, out exchange, out product, out instrument, out date))
90 | {
91 | if (string.IsNullOrEmpty(exchange))
92 | {
93 | exchange = DefaultExchange;
94 | }
95 |
96 | DirectoryInfo DI_TradingDay = new DirectoryInfo(Path.Combine(OutputPath_TradingDay, date));
97 | if (!DI_TradingDay.Exists)
98 | DI_TradingDay.Create();
99 | string Path_TradingDay = Path.Combine(DI_TradingDay.FullName, f.Name);
100 |
101 | // 将当前目录下内容复制到指定日期目录
102 | File.Copy(f.FullName, Path_TradingDay, true);
103 |
104 | {
105 | DirectoryInfo DI_Instrument = new DirectoryInfo(Path.Combine(OutputPath_Instrument, exchange, product, instrument));
106 | if (!DI_Instrument.Exists)
107 | DI_Instrument.Create();
108 | string Path_Instrument = Path.Combine(DI_Instrument.FullName, f.Name);
109 | // 将当前目录下内容压缩到指定合约目录下
110 |
111 | // 文件已经打开的情况下,无法进行压缩,这个地方处理一下
112 | PathHelper.SevenZipFile(SevenZipExePath, Path_Instrument + ".7z", Path_TradingDay);
113 | }
114 |
115 | // 只有备份了一份,才会去删除
116 | if (Clear_DataPath)
117 | {
118 | File.Delete(f.FullName);
119 | }
120 |
121 | // 记录下处理了哪些交易日
122 | Set_TradingDay.Add(DI_TradingDay.FullName);
123 |
124 | Log.Info("处理完:{0}", f.FullName);
125 | }
126 | else
127 | {
128 | //无法识别,需人工处理
129 | Log.Info("无法识别:{0}", f.FullName);
130 | }
131 | }
132 |
133 | // 对交易日进行压缩
134 | foreach (var d in Set_TradingDay)
135 | {
136 | Log.Info("压缩交易日目录:{0}", d);
137 | PathHelper.SevenZipDirectory(SevenZipExePath, d + ".7z", d);
138 |
139 | Log.Info("转换交易日目录:{0}", d);
140 | HDF5_Convert(d + ".h5", d, Log);
141 | }
142 |
143 | // 删除
144 | if (Clear_OutputPath_TradingDay)
145 | {
146 | foreach (var d in Set_TradingDay)
147 | {
148 | Log.Info("删除交易日目录:{0}", d);
149 | var di = new DirectoryInfo(d);
150 | if(di.Exists)
151 | di.Delete(true);
152 | }
153 | }
154 |
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/ArchiveData/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ArchiveData")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ArchiveData")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("80e02079-917c-4883-81e5-866211e64c96")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ArchiveData/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/DataDownload/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/DataDownload/DataDownload.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.IO.IsolatedStorage;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Web;
11 |
12 | namespace DataDownload
13 | {
14 | public class DataDownload
15 | {
16 | public const string URL_Realtime = "download.php?type=realtime&exchange={0}&instrument={1}";
17 | public const string URL_TradingDay = "download.php?type=tradingday&tradingday={0}";
18 | public const string URL_Historical = "download.php?type=historical&exchange={0}&product={1}&instrument={2}&tradingday={3}";
19 |
20 | public string BASE_URL = "http://localhost/";
21 |
22 | public string PATH_Realtime = @"E:\test\Data";
23 | public string PATH_TradingDay = @"E:\test\Data_TradingDay";
24 | public string PATH_Historical = @"E:\test\Data_Instrument";
25 |
26 | private string _USERNAME;
27 | public string USERNAME
28 | {
29 | get { return _USERNAME; }
30 | set {
31 | _USERNAME = value;
32 |
33 | Cookies = (Dictionary)Load(_USERNAME, Cookies);
34 | foreach (var cook in Cookies.Values)
35 | {
36 | CookieContainer.Add(cook);
37 | }
38 | }
39 | }
40 | public string PASSWORD { get; set; }
41 |
42 | private CookieContainer CookieContainer = new CookieContainer();
43 | private Dictionary Cookies = new Dictionary();
44 |
45 | public Tuple GetRealtime(string exchange, string instrument)
46 | {
47 | string url = string.Format(BASE_URL + URL_Realtime, HttpUtility.UrlEncode(exchange), HttpUtility.UrlEncode(instrument));
48 | return DownloadFile(url, PATH_Realtime);
49 | }
50 |
51 | public Tuple GetTradingDay(int tradingDay)
52 | {
53 | string url = string.Format(BASE_URL + URL_TradingDay,tradingDay);
54 | return DownloadFile(url, PATH_TradingDay);
55 | }
56 |
57 | public Tuple GetHistorical(string exchange, string product, string instrument, int tradingDay)
58 | {
59 | string url = string.Format(BASE_URL + URL_Historical, HttpUtility.UrlEncode(exchange), HttpUtility.UrlEncode(product), HttpUtility.UrlEncode(instrument), tradingDay);
60 | string newpath = Path.Combine(PATH_Historical, exchange, product, instrument);
61 | return DownloadFile(url, newpath);
62 | }
63 |
64 | public Tuple GetHistorical(string exchange, string product, string instrument, DateTime tradingDay)
65 | {
66 | int date = tradingDay.Year * 10000 + tradingDay.Month * 100 + tradingDay.Day;
67 | return GetHistorical(exchange, product, instrument, date);
68 | }
69 |
70 | public List> GetHistorical(string exchange, string product, string instrument, int datatime1,int datatime2)
71 | {
72 | List> file_paths = new List>();
73 |
74 | DateTime _datetime1 = new DateTime(datatime1 / 10000, datatime1 % 10000 / 100, datatime1 % 100);
75 | DateTime _datatime2 = new DateTime(datatime2 / 10000, datatime2 % 10000 / 100, datatime2 % 100);
76 |
77 | for (DateTime datetime = _datetime1; datetime <= _datatime2; datetime = datetime.AddDays(1))
78 | {
79 | if (datetime.DayOfWeek == DayOfWeek.Saturday || datetime.DayOfWeek == DayOfWeek.Sunday)
80 | continue;
81 |
82 | file_paths.Add(GetHistorical(exchange, product, instrument, datetime));
83 | }
84 |
85 | return file_paths;
86 | }
87 |
88 | #region Cookie写入
89 | private static JsonSerializerSettings jSetting = new JsonSerializerSettings()
90 | {
91 | // json文件格式使用非紧凑模式
92 | //NullValueHandling = NullValueHandling.Ignore,
93 | //DefaultValueHandling = DefaultValueHandling.Ignore,
94 | Formatting = Formatting.Indented,
95 | };
96 |
97 | protected void Save(string file, object obj)
98 | {
99 | IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForAssembly();
100 | using (FileStream fs = myIsolatedStorage.OpenFile(file, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
101 | {
102 | using (TextWriter writer = new StreamWriter(fs))
103 | {
104 | writer.Write("{0}", JsonConvert.SerializeObject(obj, obj.GetType(), jSetting));
105 | writer.Close();
106 | }
107 | }
108 | }
109 | protected object Load(string file, object obj)
110 | {
111 | try
112 | {
113 | object ret;
114 | IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForAssembly();
115 | using (FileStream fs = myIsolatedStorage.OpenFile(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
116 | {
117 | using (TextReader reader = new StreamReader(fs))
118 | {
119 | ret = JsonConvert.DeserializeObject(reader.ReadToEnd(), obj.GetType());
120 | reader.Close();
121 | }
122 | }
123 |
124 | return ret;
125 | }
126 | catch
127 | {
128 | }
129 | return obj;
130 | }
131 |
132 | private void SaveCookie(HttpWebResponse rsp)
133 | {
134 | if (rsp.Headers["Set-Cookie"] != null)
135 | {
136 | foreach (Cookie cook in rsp.Cookies)
137 | {
138 | Cookies[cook.Name] = cook;
139 | Save(_USERNAME, Cookies);
140 |
141 | //Console.WriteLine("Cookie:");
142 | //Console.WriteLine("{0} = {1}", cook.Name, cook.Value);
143 | //Console.WriteLine("Domain: {0}", cook.Domain);
144 | //Console.WriteLine("Path: {0}", cook.Path);
145 | //Console.WriteLine("Port: {0}", cook.Port);
146 | //Console.WriteLine("Secure: {0}", cook.Secure);
147 |
148 | //Console.WriteLine("When issued: {0}", cook.TimeStamp);
149 | //Console.WriteLine("Expires: {0} (expired? {1})",
150 | // cook.Expires, cook.Expired);
151 | //Console.WriteLine("Don't save: {0}", cook.Discard);
152 | //Console.WriteLine("Comment: {0}", cook.Comment);
153 | //Console.WriteLine("Uri for comments: {0}", cook.CommentUri);
154 | //Console.WriteLine("Version: RFC {0}", cook.Version == 1 ? "2109" : "2965");
155 |
156 | //// Show the string representation of the cookie.
157 | //Console.WriteLine("String: {0}", cook.ToString());
158 | }
159 | }
160 | }
161 | #endregion
162 |
163 | protected Tuple DownloadFile(string url, string local_path)
164 | {
165 | var httpStatusCode = 200;
166 | string file_fullname = "";
167 | string target = "";
168 |
169 | // 由于不知道本地文件名是多少,没法进行断点继传
170 | HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
171 | NetworkCredential nc = new NetworkCredential(USERNAME, PASSWORD);
172 | req.Credentials = nc;
173 | req.CookieContainer = CookieContainer;
174 |
175 | try
176 | {
177 | using (HttpWebResponse wr = (HttpWebResponse)req.GetResponse())
178 | {
179 | string desc = wr.Headers["Content-Disposition"];
180 | if (desc != null)
181 | {
182 | string fstr = "filename=";
183 | int pos1 = desc.IndexOf(fstr);
184 | if (pos1 > 0)
185 | {
186 | string fn = desc.Substring(pos1 + fstr.Length);
187 | if (fn != "")
188 | target = fn;
189 | }
190 | }
191 |
192 | using (Stream stream = wr.GetResponseStream())
193 | {
194 | file_fullname = Path.Combine(local_path, target);
195 | DirectoryInfo di = new DirectoryInfo(local_path);
196 | if (!di.Exists)
197 | di.Create();
198 |
199 | //文件流,流信息读到文件流中,读完关闭
200 | using (FileStream fs = File.Create(file_fullname))
201 | {
202 | //建立字节组,并设置它的大小是多少字节
203 | byte[] bytes = new byte[10240];
204 | int n = 0;
205 | do
206 | {
207 | //一次从流中读多少字节,并把值赋给N,当读完后,N为0,并退出循环
208 | n = stream.Read(bytes, 0, 1024);
209 | fs.Write(bytes, 0, n); //将指定字节的流信息写入文件流中
210 | } while (n > 0);
211 | }
212 | File.SetLastWriteTime(file_fullname, wr.LastModified);
213 | }
214 |
215 | SaveCookie(wr);
216 | }
217 | }
218 | catch (WebException ex)
219 | {
220 | var rsp = ex.Response as HttpWebResponse;
221 | httpStatusCode = (int)rsp.StatusCode;
222 | file_fullname = string.Format("{0} - {1}", ex.Message, url);
223 |
224 | SaveCookie(rsp);
225 | }
226 | catch (Exception ex)
227 | {
228 | httpStatusCode = 0;
229 | file_fullname = string.Format("{0} - {1}", ex.Message, url);
230 | }
231 |
232 | return new Tuple(httpStatusCode,file_fullname);
233 | }
234 |
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/DataDownload/DataDownload.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {529AAC14-B1FF-4524-929D-40756CAB260B}
8 | Exe
9 | Properties
10 | DataDownload
11 | DataDownload
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | ..\bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
40 | True
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | if not exist "$(TargetDir)bin32" md "$(TargetDir)bin32"
65 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin32\*.*" "$(TargetDir)bin32"
66 | if not exist "$(TargetDir)bin64" md "$(TargetDir)bin64"
67 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin64\*.*" "$(TargetDir)bin64"
68 |
69 |
76 |
--------------------------------------------------------------------------------
/DataDownload/PathHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.RegularExpressions;
7 | using System.Threading.Tasks;
8 |
9 | namespace ArchiveData
10 | {
11 | //"D:\Program Files\7-Zip\7z.exe" a -t7z "D:\test\Data_TradingDay\20150326.7z" "D:\test\Data_TradingDay\20150326\*" -m0=PPMd -mx=9
12 | //"D:\Program Files\7-Zip\7z.exe" a -t7z "D:\test\Data_TradingDay\20150326.7z" "D:\test\Data_TradingDay\20150326\*" -m0=PPMd -mx=9
13 |
14 | public class PathHelper
15 | {
16 | public static bool SplitFileName(string fileName, out string exchange, out string product,
17 | out string instrument, out string date)
18 | {
19 | exchange = string.Empty;
20 | product = string.Empty;
21 | instrument = string.Empty;
22 | date = string.Empty;
23 | // IF1503.CFFEX_20150430
24 | // IF1503._20150430
25 | // IO1506-C-2768._20150430
26 | // SR503C1507.CZCE_20150430
27 | // 600000.SSE_20150506
28 | // SPC a1506&b1507._20150501
29 | // IO1506-C-2768&IO1506-C-2768._20150501
30 | Regex regex1 = new Regex(@"([A-za-z0-9\-& ]*)\.([A-za-z]*)_(\d{4,8})");
31 | Match match1 = regex1.Match(fileName);
32 | if (match1.Success)
33 | {
34 | instrument = match1.Groups[1].ToString();
35 | exchange = match1.Groups[2].ToString();
36 | date = match1.Groups[3].ToString();
37 |
38 | if (instrument.IndexOf("&") > -1)
39 | {
40 | // SPC a1506&b1507
41 | // IO1506-C-2768&IO1506-C-2768
42 | char[] arr = instrument.ToCharArray();
43 | for (int i = 0; i < arr.Length; i++)
44 | {
45 | if (!(arr[i] >= '0' && arr[i] <= '9' || arr[i]=='-'))
46 | {
47 | product += arr[i];
48 | }
49 | }
50 | return true;
51 | }
52 | else
53 | {
54 | // IF1503
55 | // SR503
56 | // IO1503-C-2500
57 | // SR503C500
58 | // 600000
59 | Regex regex2 = new Regex(@"([A-za-z]*)([0-9]+)([-CP]?)");
60 | Match match2 = regex2.Match(instrument);
61 | if (match2.Success)
62 | {
63 | if (string.IsNullOrEmpty(match2.Groups[3].ToString()))
64 | {
65 | product = match2.Groups[1].ToString();
66 | }
67 | else
68 | {
69 | product = match2.Groups[1].ToString() + match2.Groups[2].ToString();
70 | }
71 | return true;
72 | }
73 | }
74 | }
75 | return false;
76 | }
77 |
78 |
79 | public static string SevenZipDirectory(string exe, string target, string directory)
80 | {
81 | // 注意当7z中已经有文件时是添加
82 |
83 | //"D:\Program Files\7-Zip\7z.exe" a -t7z "D:\test\Data_TradingDay\20150326.7z" "D:\test\Data_TradingDay\20150326\*" -m0=PPMd -mx=9
84 | string cmd = string.Format("a -t7z \"{0}\" \"{1}\\*\" -m0=PPMd -mx=9",target, directory);
85 | var proc = Process.Start(exe,cmd);
86 | proc.WaitForExit();
87 | return cmd;
88 | }
89 |
90 | public static string SevenZipFile(string exe, string target, string source)
91 | {
92 | //"D:\Program Files\7-Zip\7z.exe" a -t7z "D:\test\Data_TradingDay\20150326.7z" "D:\test\Data_TradingDay\20150326\*" -m0=PPMd -mx=9
93 | string cmd = string.Format("a -t7z \"{0}\" \"{1}\" -m0=PPMd -mx=9", target, source);
94 | ProcessStartInfo ps = new ProcessStartInfo(exe);
95 | ps.UseShellExecute = false;
96 | ps.CreateNoWindow = true;
97 | ps.Arguments = cmd;
98 | var proc = Process.Start(ps);
99 | proc.WaitForExit();
100 | return cmd;
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/DataDownload/Program.cs:
--------------------------------------------------------------------------------
1 | using ArchiveData;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | //using HDF.PInvoke;
10 | using System.Runtime.InteropServices;
11 |
12 | namespace DataDownload
13 | {
14 | class Program
15 | {
16 | static void Main(string[] args)
17 | {
18 | var dd = new DataDownload();
19 | dd.USERNAME = "guest";
20 | dd.PASSWORD = "guest";
21 | dd.BASE_URL = "http://localhost/";
22 | //dd.PATH_Historical = "";
23 | var ll = dd.GetHistorical("CFFEX", "IF&IF", "IF1504&IF1505", 20150330, 20150520);
24 | var l2 = dd.GetHistorical("CFFEX", "IF", "IF1504", 20150330, 20150520);
25 | foreach(var l in ll)
26 | {
27 | Console.WriteLine(l.Item1 + l.Item2);
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/DataDownload/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("DataDownload")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("DataDownload")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("14b49c8a-7287-4621-bf2d-3b0525a80d82")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/DataDownload/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/DataReceiver/ApiBase.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using XAPI;
10 | using XAPI.Callback;
11 | using System.Runtime.Serialization.Json;
12 | using System.Runtime.Serialization;
13 |
14 | namespace DataReceiver
15 | {
16 | public class ApiBase
17 | {
18 | public int TradingDay;
19 | public string ConfigPath;
20 | public string DataPath;
21 | public string InstrumentInfoListFileName = @"InstrumentInfoList.json";
22 | public List InstrumentInfoList = new List();
23 |
24 | protected bool bIsLast;
25 |
26 | public List XApiList = new List();
27 |
28 | private static JsonSerializerSettings jSetting = new JsonSerializerSettings()
29 | {
30 | // json文件格式使用非紧凑模式
31 | //NullValueHandling = NullValueHandling.Ignore,
32 | //DefaultValueHandling = DefaultValueHandling.Ignore,
33 | Formatting = Formatting.Indented,
34 | };
35 |
36 | protected void Save(string path, string file, object obj)
37 | {
38 | using (FileStream fs = File.Open(Path.Combine(path, file), FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
39 | {
40 | using (TextWriter writer = new StreamWriter(fs))
41 | {
42 | writer.Write("{0}", JsonConvert.SerializeObject(obj, obj.GetType(), jSetting));
43 | writer.Close();
44 | }
45 | }
46 | }
47 | protected object Load(string path, string file, object obj)
48 | {
49 | try
50 | {
51 | object ret;
52 | using (FileStream fs = File.Open(Path.Combine(path, file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
53 | {
54 | using (TextReader reader = new StreamReader(fs))
55 | {
56 | ret = JsonConvert.DeserializeObject(reader.ReadToEnd(), obj.GetType());
57 | reader.Close();
58 | }
59 | }
60 |
61 | return ret;
62 | }
63 | catch
64 | {
65 | }
66 | return obj;
67 | }
68 |
69 | protected object Load2(string path, string file, object obj)
70 | {
71 | try
72 | {
73 | object ret;
74 | using (FileStream fs = File.Open(Path.Combine(path, file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
75 | {
76 | // 虽然是内置的,但因为DateTime转换不是想要的,所以弃用
77 | var serializer = new DataContractJsonSerializer(obj.GetType(), new DataContractJsonSerializerSettings() {
78 | DateTimeFormat = new DateTimeFormat("HH:MM:ss")
79 | });
80 | ret = serializer.ReadObject(fs);
81 | }
82 |
83 | return ret;
84 | }
85 | catch(Exception ex)
86 | {
87 | int i = 1;
88 | }
89 | return obj;
90 | }
91 |
92 | public virtual void Disconnect()
93 | {
94 | foreach (var api in XApiList)
95 | {
96 | api.Disconnect();
97 | }
98 | }
99 |
100 | ///
101 | /// 超时退出返回false
102 | /// 正常退出返回true
103 | ///
104 | ///
105 | ///
106 | public bool WaitConnectd(int timeout)
107 | {
108 | DateTime dt = DateTime.Now;
109 |
110 | do
111 | {
112 | bool IsConnected = true;
113 | foreach (var api in XApiList)
114 | {
115 | if (!api.IsConnected)
116 | {
117 | IsConnected = false;
118 | break;
119 | }
120 | }
121 |
122 | if (IsConnected)
123 | return true;
124 |
125 | // 超时退出
126 | if ((DateTime.Now - dt).TotalMilliseconds >= timeout)
127 | {
128 | return false;
129 | }
130 | Thread.Sleep(1000);
131 | } while (true);
132 | }
133 |
134 | ///
135 | /// 超时退出返回false
136 | /// 正常退出返回true
137 | ///
138 | ///
139 | ///
140 | public bool WaitIsLast(int timeout)
141 | {
142 | DateTime dt = DateTime.Now;
143 | while (!bIsLast)
144 | {
145 | if ((DateTime.Now - dt).TotalMilliseconds >= timeout)
146 | {
147 | return false;
148 | }
149 | Thread.Sleep(1000);
150 | }
151 | return true;
152 | }
153 |
154 | protected virtual void OnConnectionStatus(object sender, ConnectionStatus status, ref RspUserLoginField userLogin, int size1)
155 | {
156 | if (size1 > 0)
157 | {
158 | if (userLogin.RawErrorID != 0)
159 | {
160 | (sender as XApi).GetLog().Info("{0}:{1}", status, userLogin.ToFormattedStringShort());
161 | }
162 | else
163 | {
164 | (sender as XApi).GetLog().Info("{0}:{1}", status, userLogin.ToFormattedStringLong());
165 | }
166 | }
167 | else
168 | {
169 | (sender as XApi).GetLog().Info("{0}", status);
170 | }
171 | if (status == ConnectionStatus.Logined)
172 | {
173 | TradingDay = userLogin.TradingDay;
174 | }
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/DataReceiver/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/DataReceiver/DRTickWriter.cs:
--------------------------------------------------------------------------------
1 | using Ideafixxxer.Generics;
2 | using QuantBox.Data.Serializer.V2;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using XAPI;
9 |
10 | namespace DataReceiver
11 | {
12 | ///
13 | ///
14 | ///
15 | public class DRTickWriter:TickWriter
16 | {
17 | public string OutputFormat;
18 | public bool IsHdf5;
19 |
20 | public DRTickWriter(string path, string outputFormat):base(path)
21 | {
22 | OutputFormat = outputFormat;
23 |
24 | IsHdf5 = string.Compare(OutputFormat, "pd0", true) != 0;
25 | }
26 |
27 | // 目前先不处理港股的tickSize变化的那种行情
28 | PbTick CreateTick(ref DepthMarketDataNClass pDepthMarketData, PbTickCodec codec)
29 | {
30 | var tick = new PbTick();
31 | tick.DepthList = new List();
32 | tick.Config = codec.Config;
33 |
34 | tick.TradingDay = pDepthMarketData.TradingDay;
35 | tick.ActionDay = pDepthMarketData.ActionDay;
36 | tick.Time_HHmm = pDepthMarketData.UpdateTime / 100;
37 | tick.Time_____ssf__ = pDepthMarketData.UpdateTime % 100 * 10 + pDepthMarketData.UpdateMillisec / 100;
38 | tick.Time________ff = pDepthMarketData.UpdateMillisec % 100;
39 | // 数据接收器时计算本地与交易所的行情时间差
40 | // 1.这个地方是否保存?
41 | // 2.到底是XAPI中提供还是由接收器提供?
42 | //tick.LocalTime_Msec = (int)(DateTime.Now - codec.GetActionDayDateTime(tick)).TotalMilliseconds;
43 |
44 | codec.SetSymbol(tick, pDepthMarketData.Symbol);
45 | if (pDepthMarketData.Exchange != ExchangeType.Undefined)
46 | codec.SetExchange(tick, Enum.ToString(pDepthMarketData.Exchange));
47 | codec.SetLowerLimitPrice(tick, pDepthMarketData.LowerLimitPrice);
48 | codec.SetUpperLimitPrice(tick, pDepthMarketData.UpperLimitPrice);
49 |
50 | codec.SetOpen(tick, pDepthMarketData.OpenPrice);
51 | codec.SetHigh(tick, pDepthMarketData.HighestPrice);
52 | codec.SetLow(tick, pDepthMarketData.LowestPrice);
53 | codec.SetClose(tick, pDepthMarketData.ClosePrice);
54 |
55 | codec.SetVolume(tick, (long)pDepthMarketData.Volume);
56 | codec.SetOpenInterest(tick, (long)pDepthMarketData.OpenInterest);
57 | codec.SetTurnover(tick, pDepthMarketData.Turnover);//一定要设置合约乘数才能最优保存
58 | codec.SetAveragePrice(tick, pDepthMarketData.AveragePrice);
59 | codec.SetLastPrice(tick, pDepthMarketData.LastPrice);
60 | codec.SetSettlementPrice(tick, pDepthMarketData.SettlementPrice);
61 |
62 | codec.SetPreClosePrice(tick, pDepthMarketData.PreClosePrice);
63 | codec.SetPreSettlementPrice(tick, pDepthMarketData.PreSettlementPrice);
64 | codec.SetPreOpenInterest(tick, (long)pDepthMarketData.PreOpenInterest);
65 |
66 | for(int i = pDepthMarketData.Bids.Length - 1;i>=0;--i)
67 | {
68 | var bid = pDepthMarketData.Bids[i];
69 | if (bid.Size == 0)
70 | break;
71 |
72 | // 记录卖一价
73 | if (i == 0)
74 | {
75 | codec.SetAskPrice1(tick, bid.Price);
76 | tick.AskPrice1 += 1;
77 | }
78 |
79 | tick.DepthList.Add(new DepthItem(codec.PriceToTick(bid.Price), bid.Size, bid.Count));
80 | }
81 |
82 | for (int i = 0; i < pDepthMarketData.Asks.Length; ++i)
83 | {
84 | var ask = pDepthMarketData.Asks[i];
85 |
86 | if (ask.Size == 0)
87 | break;
88 |
89 | // 记录卖一价
90 | if (i == 0)
91 | {
92 | codec.SetAskPrice1(tick, ask.Price);
93 | }
94 |
95 | tick.DepthList.Add(new DepthItem(codec.PriceToTick(ask.Price), ask.Size, ask.Count));
96 | }
97 |
98 | return tick;
99 | }
100 |
101 | public bool Write(ref DepthMarketDataNClass pDepthMarketData)
102 | {
103 | //if(IsHdf5)
104 | //{
105 | // // 输出
106 | // return true;
107 | //}
108 | //else
109 | {
110 | QuantBox.Data.Serializer.V2.TickWriter.WriterDataItem item;
111 | if (Items.TryGetValue(pDepthMarketData.Symbol, out item))
112 | {
113 | item.Tick = CreateTick(ref pDepthMarketData, item.Serializer.Codec);
114 | base.Write(item, item.Tick);
115 | return true;
116 | }
117 | return false;
118 | }
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/DataReceiver/DataReceiver.cs:
--------------------------------------------------------------------------------
1 | using FileMonitor;
2 | using Newtonsoft.Json;
3 | using NLog;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Diagnostics;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Reflection;
10 | using System.Text;
11 | using System.Text.RegularExpressions;
12 | using System.Threading;
13 | using System.Threading.Tasks;
14 | using System.Threading.Tasks.Dataflow;
15 | using XAPI;
16 | using XAPI.Callback;
17 | using Tom.Kdb;
18 |
19 | namespace DataReceiver
20 | {
21 | public class DataReceiver : ApiBase
22 | {
23 | public DRTickWriter TickWriter;
24 | public KdbWriter KdbWriter;
25 |
26 | public List ConnectionConfigList;
27 | public List IncludeFilterList;
28 | public List ExcludeFilterList;
29 | public List ScheduleTasksList;
30 |
31 | public string ConnectionConfigListFileName = @"ConnectionConfigList.json";
32 | public string IncludeFilterListFileName = @"IncludeFilterList.json";
33 | public string ExcludeFilterListFileName = @"ExcludeFilterList.json";
34 |
35 | public string SaveAsFilteredInstrumentInfoListFileName = @"FilteredInstrumentInfoList.json";
36 | public string SaveAsSubscribedInstrumentInfoListFileName = @"SubscribedInstrumentInfoList.json";
37 |
38 | public string SaveAsTradingDayFileName = @"TradingDay.json";
39 |
40 | public string ScheduleTasksListFileName = @"ScheduleTasks.json";
41 |
42 | private System.Timers.Timer _Timer = new System.Timers.Timer();
43 |
44 | public ActionBlock Input_pd0;
45 | public ActionBlock Input_kdb;
46 | private Logger Log = LogManager.GetCurrentClassLogger();
47 |
48 | #region 配置文件重新加载
49 | private Dictionary> watchers = new Dictionary>();
50 |
51 | public void WatcherStrat(string path, string filter)
52 | {
53 | string key = Path.Combine(path, filter);
54 | Tuple tuple;
55 | if (!watchers.TryGetValue(key, out tuple))
56 | {
57 | WatcherTimer timer = new WatcherTimer(OnReload);
58 |
59 | FileSystemWatcher watcher = new FileSystemWatcher();
60 | watcher.Path = path;
61 | watcher.Filter = filter;
62 | watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
63 | watcher.Changed += new FileSystemEventHandler(timer.OnFileChanged);
64 | watcher.Deleted += new FileSystemEventHandler(timer.OnFileChanged);
65 | watcher.EnableRaisingEvents = true;
66 |
67 | tuple = new Tuple(watcher, timer);
68 | }
69 | watchers[key] = tuple;
70 | }
71 |
72 | public void WatcherStop()
73 | {
74 | foreach (var watcher in watchers.Values)
75 | {
76 | watcher.Item1.EnableRaisingEvents = false;
77 | }
78 | watchers.Clear();
79 | }
80 |
81 | ///
82 | /// 文件改变事件
83 | ///
84 | ///
85 | ///
86 | private void OnReload(object source, FileSystemEventArgs e)
87 | {
88 | // 只关注这三个文件的变化
89 | if (e.FullPath.EndsWith(InstrumentInfoListFileName)
90 | || e.FullPath.EndsWith(IncludeFilterListFileName)
91 | || e.FullPath.EndsWith(ExcludeFilterListFileName)
92 | )
93 | {
94 | Log.Info("文件变动{0},{1}", e.ChangeType, e.FullPath);
95 | if (e.ChangeType == WatcherChangeTypes.Changed)
96 | {
97 | ProcessConfig(e.FullPath);
98 | }
99 | else if (e.ChangeType == WatcherChangeTypes.Deleted)
100 | {
101 | //CreateConfig(e.FullPath);
102 | }
103 | }
104 | else if (e.FullPath.EndsWith(ScheduleTasksListFileName))
105 | {
106 | ProcessScheduleTasks(e.FullPath);
107 | }
108 | }
109 |
110 | ///
111 | /// 如果加载失败就生成
112 | ///
113 | ///
114 | public void ProcessConfig(string fullPath)
115 | {
116 | List oldList = new List(InstrumentInfoList);
117 |
118 | LoadInstrumentInfoList();
119 | // 得到要订阅的表,是否覆盖原表?
120 | List newList = Filter(InstrumentInfoList);
121 | InstrumentInfoList = newList;
122 |
123 | IEnumerable _have = newList.Intersect(oldList);
124 | // 对于已经订阅的,有可能合约最小变动价位变化,所以可能需要重新更新
125 | foreach (var h in _have)
126 | {
127 | AddInstrument(h);
128 | }
129 |
130 | IEnumerable _old = oldList.Except(newList);
131 | Unsubscribe(_old);
132 | IEnumerable _new = newList.Except(oldList);
133 | int f = Subscribe(_new);
134 |
135 | Log.Info("取消订阅:{0},尝试订阅:{1},已经订阅:{2},订阅失败:{3}", _old.Count(), _new.Count(), _have.Count(), f);
136 |
137 | SaveAsInstrumentInfoList();
138 | }
139 |
140 | // 可用于定时订阅
141 | public void ReSubscribe()
142 | {
143 | Log.Info("重新订阅:{0}", InstrumentInfoList.Count());
144 | Unsubscribe(InstrumentInfoList);
145 | Subscribe(InstrumentInfoList);
146 | }
147 |
148 | public void BeforeSubscribe()
149 | {
150 | if (null != KdbWriter)
151 | {
152 | // 连接kdb
153 | KdbWriter.Connect();
154 | // 设置当前交易日
155 | KdbWriter.SetTradingDay(TradingDay);
156 | // 初始化表
157 | KdbWriter.Init();
158 | // 检查是否换日了
159 | KdbWriter.ChangeTradingDay();
160 | }
161 | }
162 |
163 | public void ProcessScheduleTasks(string fullPath)
164 | {
165 | LoadScheduleTasks();
166 |
167 | //ScheduleTasksList.Add(new Tuple(new TimeSpan(08, 50, 0), "notepad.exe"));
168 | //ScheduleTasksList.Add(new Tuple(new TimeSpan(08, 50, 0), "notepad.exe"));
169 |
170 | //Save(ConfigPath, ScheduleTasksListFileName, ScheduleTasksList);
171 | _Timer.Elapsed -= _Timer_Elapsed;
172 | _Timer.Elapsed += _Timer_Elapsed;
173 | _Timer.Interval = 10 * 1000;
174 | _Timer.Enabled = true;
175 | }
176 |
177 | int CheckedTime = -1;
178 |
179 | void _Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
180 | {
181 | lock (this)
182 | {
183 | _Timer.Enabled = false;
184 |
185 | int now = e.SignalTime.Hour * 100 + e.SignalTime.Minute;
186 | if (CheckedTime == now)
187 | {
188 | _Timer.Enabled = true;
189 | return;
190 | }
191 | CheckedTime = now;
192 |
193 | foreach (var it in ScheduleTasksList)
194 | {
195 | try
196 | {
197 | DateTime dt = e.SignalTime.Date.Add(it.Item1);
198 | int t = dt.Hour * 100 + dt.Minute;
199 | if (t == now)
200 | {
201 | Log.Info("执行任务:{0} {1} {2}", it.Item1, it.Item2, it.Item3);
202 | if (it.Item2.ToLower().EndsWith(".exe"))
203 | {
204 | var proc = Process.Start(it.Item2, it.Item3);
205 | //proc.WaitForExit();
206 | }
207 | else
208 | {
209 | // 执行指定方法
210 | MethodInfo mi = this.GetType().GetMethod(it.Item2);
211 | mi.Invoke(this, new object[] { });
212 | }
213 |
214 | break;
215 | }
216 | }
217 | catch (Exception e1)
218 | {
219 | Log.Error(e1.Message);
220 | }
221 | }
222 |
223 | _Timer.Enabled = true;
224 | }
225 | }
226 | #endregion
227 |
228 | public DataReceiver()
229 | {
230 | Input_pd0 = new ActionBlock((x) => OnInputMarketData_pd0(x));
231 | Input_kdb = new ActionBlock((x) => OnInputMarketData_kdb(x));
232 | }
233 |
234 | public void Save()
235 | {
236 | Save(ConfigPath, ConnectionConfigListFileName, ConnectionConfigList);
237 | Save(ConfigPath, InstrumentInfoListFileName, InstrumentInfoList);
238 | Save(ConfigPath, IncludeFilterListFileName, IncludeFilterList);
239 | Save(ConfigPath, ExcludeFilterListFileName, ExcludeFilterList);
240 | }
241 |
242 | ///
243 | /// 这里保存的是过滤后的合约列表,这不是订阅成功的列表
244 | ///
245 | public void SaveAsInstrumentInfoList()
246 | {
247 | Save(DataPath, SaveAsFilteredInstrumentInfoListFileName, InstrumentInfoList);
248 | }
249 |
250 | public void SaveAsTradingDay()
251 | {
252 | Save(DataPath, SaveAsTradingDayFileName, TradingDay);
253 | }
254 |
255 | public void LoadConnectionConfig()
256 | {
257 | ConnectionConfigList = new List();
258 |
259 | ConnectionConfigList = (List)Load(ConfigPath, ConnectionConfigListFileName, ConnectionConfigList);
260 |
261 | if (ConnectionConfigList == null)
262 | ConnectionConfigList = new List();
263 | }
264 |
265 | public void LoadInstrumentInfoList()
266 | {
267 | InstrumentInfoList = new List();
268 | IncludeFilterList = new List();
269 | ExcludeFilterList = new List();
270 |
271 | InstrumentInfoList = (List)Load(ConfigPath, InstrumentInfoListFileName, InstrumentInfoList);
272 | IncludeFilterList = (List)Load(ConfigPath, IncludeFilterListFileName, IncludeFilterList);
273 | ExcludeFilterList = (List)Load(ConfigPath, ExcludeFilterListFileName, ExcludeFilterList);
274 |
275 | if (InstrumentInfoList == null)
276 | InstrumentInfoList = new List();
277 | if (IncludeFilterList == null)
278 | IncludeFilterList = new List();
279 | if (ExcludeFilterList == null)
280 | ExcludeFilterList = new List();
281 | }
282 |
283 | public void LoadScheduleTasks()
284 | {
285 | ScheduleTasksList = new List();
286 |
287 | ScheduleTasksList = (List)Load(ConfigPath, ScheduleTasksListFileName, ScheduleTasksList);
288 | if (ScheduleTasksList == null)
289 | ScheduleTasksList = new List();
290 |
291 | Log.Info("加载计划任务数:{0}", ScheduleTasksList.Count);
292 | }
293 |
294 | public void Connect()
295 | {
296 | // 查看有多少种连接
297 | int j = 0;
298 | foreach (var cc in ConnectionConfigList)
299 | {
300 | // 建立多个连接
301 | for (int i = 0; i < cc.SessionLimit; ++i)
302 | {
303 | XApi api = new XApi(cc.LibPath);
304 | api.Server = cc.Server;
305 | api.User = cc.User;
306 | api.Log = LogManager.GetLogger(string.Format("{0}.{1}.{2}.{3}", api.Server.BrokerID, api.User.UserID, j, i));
307 |
308 | api.MaxSubscribedInstrumentsCount = cc.SubscribePerSession;
309 |
310 | api.OnConnectionStatus = OnConnectionStatus;
311 | api.OnRtnDepthMarketData = OnRtnDepthMarketData;
312 |
313 | api.Connect();
314 |
315 | XApiList.Add(api);
316 | }
317 | ++j;
318 | }
319 | }
320 |
321 | // 可用来定时断开连接
322 | public override void Disconnect()
323 | {
324 | base.Disconnect();
325 | if (null == KdbWriter)
326 | return;
327 |
328 | // 这里写在后面是为了让行情先断开,等最后的数据插件入到数据库中后再保存
329 | Log.Info("Disconnect 中主动进行保存");
330 | KdbWriter.Disconnect();
331 | }
332 |
333 | // 可用来定时保存数据,由脚本来触发
334 | // 就算连接已经断开,但在再时重新登录前,因为没法获得新的数据,还会是用老的交易日
335 | public void SaveKdbData()
336 | {
337 | if (null == KdbWriter)
338 | return;
339 |
340 | KdbWriter.Save(TradingDay);
341 | }
342 |
343 | public bool Contains(string szInstrument, string szExchange)
344 | {
345 | foreach (var api in XApiList)
346 | {
347 | if (api.SubscribedInstrumentsContains(szInstrument, szExchange))
348 | {
349 | return true;
350 | }
351 | }
352 | return false;
353 | }
354 |
355 | public List Filter(List list)
356 | {
357 | List newList = new List();
358 |
359 | foreach (var i in list)
360 | {
361 | // 查看是否需要订阅
362 | InstrumentFilterConfig match1 = Match(i.Symbol, IncludeFilterList);
363 |
364 | if (match1 != null)
365 | {
366 | i.Time_ssf_Diff = match1.Time_ssf_Diff;
367 | // 包含,需要订阅
368 |
369 | InstrumentFilterConfig match2 = Match(i.Symbol, ExcludeFilterList);
370 | if (match2 == null)
371 | {
372 | newList.Add(i);
373 | //Console.WriteLine("合约{0}匹配于{1}排除列表", i.Symbol, ExcludeFilterListFileName);
374 | }
375 | else
376 | {
377 | //Console.WriteLine("合约{0}匹配于{1}排除列表", i.Symbol, ExcludeFilterListFileName);
378 | }
379 | }
380 | else
381 | {
382 | //Console.WriteLine("合约{0}不匹配于{1}包含列表", i.Symbol, IncludeFilterListFileName);
383 | }
384 | }
385 |
386 | return newList;
387 | }
388 |
389 | public void AddInstrument(InstrumentInfo i)
390 | {
391 | TickWriter.AddInstrument(string.Format("{0}.{1}", i.Instrument, i.Exchange), i.TickSize, i.Factor, i.Time_ssf_Diff);
392 | TickWriter.AddInstrument(string.Format("{0}.", i.Instrument), i.TickSize, i.Factor, i.Time_ssf_Diff);
393 | //TickWriter.AddInstrument(string.Format("{0}", i.Instrument), i.TickSize, i.Factor, i.Time_ssf_Diff);
394 | }
395 |
396 | public void RemoveInstrument(InstrumentInfo i)
397 | {
398 | TickWriter.RemoveInstrument(string.Format("{0}.{1}", i.Instrument, i.Exchange));
399 | TickWriter.RemoveInstrument(string.Format("{0}.", i.Instrument));
400 | //TickWriter.RemoveInstrument(string.Format("{0}", i.Instrument));
401 | }
402 |
403 | ///
404 | /// 订阅
405 | ///
406 | ///
407 | public int Subscribe(IEnumerable list)
408 | {
409 | List SubscribedInstrumentInfoList = new List();
410 |
411 | int x = 0;
412 | foreach (var i in list)
413 | {
414 | // 不包含,没有被排除,需要订阅
415 | AddInstrument(i);
416 |
417 | bool bSubscribe = false;
418 |
419 | foreach (var api in XApiList)
420 | {
421 | if (api.SubscribedInstrumentsCount < api.MaxSubscribedInstrumentsCount)
422 | {
423 | api.Subscribe(i.Instrument, i.Exchange);
424 | api.GetLog().Debug("尝试订阅:{0}.{1}", i.Instrument, i.Exchange);
425 | bSubscribe = true;
426 | SubscribedInstrumentInfoList.Add(i);
427 | break;
428 | }
429 | }
430 |
431 | if (!bSubscribe)
432 | {
433 | Log.Info("超过每个连接数可订数量,{0}.{1}", i.Instrument, i.Exchange);
434 | ++x;
435 | }
436 | }
437 |
438 | // 记录实际订阅的合约
439 | Save(DataPath, SaveAsSubscribedInstrumentInfoListFileName, SubscribedInstrumentInfoList);
440 |
441 | return x;
442 | }
443 |
444 | ///
445 | /// 取消订阅
446 | ///
447 | ///
448 | public void Unsubscribe(IEnumerable list)
449 | {
450 | foreach (var i in list)
451 | {
452 | RemoveInstrument(i);
453 |
454 | foreach (var api in XApiList)
455 | {
456 | if (api.SubscribedInstrumentsContains(i.Instrument, i.Exchange))
457 | {
458 | api.Unsubscribe(i.Instrument, i.Exchange);
459 | api.GetLog().Debug("取消订阅:{0}.{1}", i.Instrument, i.Exchange);
460 | }
461 | }
462 | }
463 | }
464 |
465 | private InstrumentFilterConfig Match(string symbol, List list)
466 | {
467 | foreach (var l in list)
468 | {
469 | Regex regex = new Regex(l.SymbolRegex);
470 | if (regex.Match(symbol).Success)
471 | {
472 | return l;
473 | }
474 | }
475 | return null;
476 | }
477 |
478 | private void OnRtnDepthMarketData(object sender, ref DepthMarketDataNClass marketData)
479 | {
480 | Input_pd0.Post(marketData);
481 | if (null == KdbWriter)
482 | return;
483 |
484 | Input_kdb.Post(marketData);
485 | }
486 |
487 | public void OnInputMarketData_pd0(DepthMarketDataNClass pDepthMarketData)
488 | {
489 | TickWriter.Write(ref pDepthMarketData);
490 | }
491 |
492 | public void OnInputMarketData_kdb(DepthMarketDataNClass pDepthMarketData)
493 | {
494 | KdbWriter.Write(ref pDepthMarketData);
495 | }
496 |
497 |
498 | private DateTime LastTime = default(DateTime);
499 | protected override void OnConnectionStatus(object sender, ConnectionStatus status, ref RspUserLoginField userLogin, int size1)
500 | {
501 | base.OnConnectionStatus(sender, status, ref userLogin, size1);
502 |
503 | // 修改成只处理最后一个,因为一般情况下,最后一个其它事件也是最后到来
504 | if(sender == XApiList.Last())
505 | {
506 | // 由于配置中肯定会设置多个行情连接,所有
507 | if (status == ConnectionStatus.Logined)
508 | {
509 | TradingDay = userLogin.TradingDay;
510 | SaveAsTradingDay();
511 |
512 | if (null != KdbWriter)
513 | {
514 | KdbWriter.SetTradingDay(TradingDay);
515 | }
516 | }
517 | else if (status == ConnectionStatus.Disconnected)
518 | {
519 | // 断开连接,可加入一接断开连接时的保存指令,由于连接数多,5秒之内不重复保存
520 | if (null != KdbWriter)
521 | {
522 | Log.Info("OnConnectionStatus 中被动进行保存");
523 | KdbWriter.Save(TradingDay);
524 | }
525 | }
526 | }
527 | }
528 | }
529 | }
530 |
--------------------------------------------------------------------------------
/DataReceiver/DataReceiver.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {9E58B4E4-342B-483A-BB7F-F89A52EF7CBF}
8 | Exe
9 | Properties
10 | DataReceiver
11 | DataReceiver
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | ..\bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
40 | True
41 |
42 |
43 | ..\packages\NLog.4.4.12\lib\net45\NLog.dll
44 |
45 |
46 | False
47 | ..\lib\QuantBox.Data.Serializer.dll
48 |
49 |
50 |
51 |
52 |
53 |
54 | False
55 | ..\packages\Microsoft.Tpl.Dataflow.4.5.24\lib\portable-net45+win8+wpa81\System.Threading.Tasks.Dataflow.dll
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | ..\lib\XAPI_CSharp.exe
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | ResXFileCodeGenerator
82 | Resources.Designer.cs
83 | Designer
84 |
85 |
86 | True
87 | Resources.resx
88 |
89 |
90 |
91 | SettingsSingleFileGenerator
92 | Settings.Designer.cs
93 |
94 |
95 | True
96 | Settings.settings
97 | True
98 |
99 |
100 |
101 |
102 | Designer
103 |
104 |
105 |
106 |
107 | rem xcopy "$(SolutionDir)lib\*.dll" "$(TargetDir)" /Y
108 | if not exist "$(TargetDir)bin32" md "$(TargetDir)bin32"
109 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin32\*.*" "$(TargetDir)bin32"
110 | if not exist "$(TargetDir)bin64" md "$(TargetDir)bin64"
111 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin64\*.*" "$(TargetDir)bin64"
112 |
113 |
120 |
--------------------------------------------------------------------------------
/DataReceiver/KdbWriter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 | using XAPI;
8 | using kx;
9 | using NLog;
10 |
11 | namespace Tom.Kdb
12 | {
13 | public class KdbWriter
14 | {
15 | public c c = null;
16 |
17 | private string Host;
18 | private int Port;
19 | private string UsernameAndPassword;
20 | private string Path;
21 | private bool SaveQuote;
22 | private int TradingDay;
23 |
24 | private Logger Log = LogManager.GetCurrentClassLogger();
25 |
26 | public KdbWriter(string host, string port, string usernameAndPassword, string path, string saveQuote)
27 | {
28 | Host = host;
29 | Port = int.Parse(port);
30 | UsernameAndPassword = usernameAndPassword;
31 | Path = path;
32 | SaveQuote = bool.Parse(saveQuote);
33 | TradingDay = 0;
34 | // TradingDay = GetTradingDay(DateTime.Now);
35 | }
36 |
37 | //private int GetTradingDay(DateTime datetime)
38 | //{
39 | // DateTime dt;
40 | // if (datetime.DayOfWeek == DayOfWeek.Friday && datetime.Hour > 16)
41 | // dt = datetime.AddDays(3).Date;
42 | // else if (datetime.DayOfWeek == DayOfWeek.Saturday)
43 | // dt = datetime.AddDays(2).Date;
44 | // else if (datetime.DayOfWeek == DayOfWeek.Sunday)
45 | // dt = datetime.AddDays(1).Date;
46 | // else
47 | // dt = datetime.AddHours(8).Date;
48 |
49 | // return int.Parse(dt.ToString("yyyyMMdd"));
50 | //}
51 |
52 | public void SetTradingDay(int tradingday)
53 | {
54 | // 由在连接Logined时,kdb还没有连接,所以不能做kdb的相关操作
55 | TradingDay = tradingday;
56 | }
57 |
58 | public void ChangeTradingDay()
59 | {
60 | // 换日后trade与quote中的数据保存后清空.
61 | //
62 | int kdbTradingday = GetKdbTradingDay();
63 | if (kdbTradingday != TradingDay && kdbTradingday != 0)
64 | {
65 | if (Save(kdbTradingday))
66 | {
67 | Log.Info("换交易日了,重新建新表");
68 | Create();
69 | }
70 | }
71 | // 登录后,订阅前,需要设置交易日,但是需要确保之前已经保存好了内存中的数据
72 | if (!SetKdbTradingDay(TradingDay))
73 | Log.Error("无法设置Kdb 的 tradingday,请检查是否无法连接q.exe 或 无法登录系统.");
74 | }
75 |
76 | public int GetKdbTradingDay()
77 | {
78 | if (KdbExists("tradingday"))
79 | {
80 | string checkStr = string.Format("tradingday");
81 | int result = (int)((long)c.k(checkStr));
82 | return result;
83 | }
84 | else return 0;
85 | }
86 |
87 | public bool SetKdbTradingDay(int tradingday)
88 | {
89 | try
90 | {
91 | string checkStr = string.Format("tradingday:{0}", tradingday);
92 | var s = c.k(checkStr);
93 | Log.Info("设置Kdb 的 tradingday 为 " + tradingday + " .");
94 | //long result = (long)s;
95 | return true;
96 | }
97 | catch
98 | {
99 | }
100 | return false;
101 | }
102 |
103 | public void Connect()
104 | {
105 | if (null != c)
106 | return;
107 |
108 | try
109 | {
110 | if (string.IsNullOrEmpty(UsernameAndPassword))
111 | c = new c(Host, Port);
112 | else
113 | c = new c(Host, Port, UsernameAndPassword);
114 | }
115 | catch (Exception e)
116 | {
117 | Log.Error(e.Message);
118 |
119 | try
120 | {
121 | if (Host != "127.0.0.1" && Host != "localhost")
122 | {
123 | c = null;
124 | return;
125 | }
126 |
127 | Log.Info("尝试运行 kdb+ 服务.");
128 | System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
129 | {
130 | UseShellExecute = true,
131 | FileName = "c:\\q\\w32\\q.exe",
132 | WindowStyle = System.Diagnostics.ProcessWindowStyle.Minimized,
133 | CreateNoWindow = false,
134 | Arguments = " -p " + Port.ToString()
135 | });
136 |
137 | // 需要一点时间
138 | System.Threading.Thread.Sleep(2000);
139 |
140 | if (string.IsNullOrEmpty(UsernameAndPassword))
141 | c = new c(Host, Port);
142 | else
143 | c = new c(Host, Port, UsernameAndPassword);
144 | }
145 | catch (Exception arg)
146 | {
147 | Log.Error("运行 q.exe 失败.");
148 | return;
149 | }
150 | }
151 |
152 | Log.Info("连接 kdb+ 成功:{0}:{1}", Host, Port);
153 | }
154 |
155 | public void Init()
156 | {
157 | // 表已经存在,不操作
158 | if (CheckTable())
159 | {
160 | return;
161 | }
162 |
163 | // 表不存在,先加载
164 | if (Load(TradingDay))
165 | {
166 | // 需要一点时间
167 | System.Threading.Thread.Sleep(500);
168 |
169 | if (CheckTable())
170 | {
171 | // 表已经存在,不操作
172 | return;
173 | }
174 | }
175 | else
176 | {
177 | // 加载也是失败的,只能创建了
178 | Create();
179 | }
180 | }
181 |
182 | public bool CheckTable()
183 | {
184 | if (!KdbExists("trade"))
185 | return false;
186 | Log.Info("已经存在trade表.");
187 | if (SaveQuote)
188 | {
189 | if (!KdbExists("quote"))
190 | return false;
191 | Log.Info("已经存在quote表.");
192 | }
193 | return true;
194 | }
195 |
196 | private bool KdbExists(string text = "trade")
197 | {
198 | if (null == c)
199 | {
200 | return false;
201 | }
202 | try
203 | {
204 | string checkStr = string.Format("type {0}", text);
205 | var result = c.k(checkStr);
206 | short s = (short)result;
207 | if (s == 98 || s == 99 || s == -7 || s == -11)
208 | return true;
209 | }
210 | catch
211 | {
212 | }
213 | return false;
214 | }
215 |
216 | public void Create()
217 | {
218 | lock (this)
219 | {
220 | try
221 | {
222 | c.ks(@"trade:([]datetime:`datetime$();sym:`symbol$();price:`float$();volume:`long$();openint:`long$())");
223 | Log.Info("创建trade表完成.");
224 | if (SaveQuote)
225 | {
226 | c.ks(@"quote:([]datetime:`datetime$();sym:`symbol$();bid:`float$();ask:`float$();bsize:`int$();asize:`int$())");
227 | Log.Info("创建quote表完成.");
228 | }
229 | }
230 | catch (Exception e)
231 | {
232 | Log.Error("创建trade/quote表失败.");
233 | }
234 | }
235 | }
236 |
237 | public bool Load(int tradingday)
238 | {
239 | try
240 | {
241 | //object result = c.k(string.Format(@"\l {0}", Path));
242 | object result1 = c.k(string.Format(@"trade: get `:{0}/{1}/{2}", Path, "trades", tradingday));
243 | Log.Info("从磁盘加载 trade 表 {0} 成功.", tradingday);
244 | }
245 | catch
246 | {
247 | Log.Error("从磁盘加载trade失败.");
248 | return false;
249 | }
250 | if (SaveQuote)
251 | {
252 | try
253 | {
254 | object result2 = c.k(string.Format(@"quote: get `:{0}/{1}/{2}", Path, "quotes", tradingday));
255 | Log.Info("从磁盘加载 quote 表 {0} 成功.", tradingday);
256 | }
257 | catch
258 | {
259 | Log.Error("从磁盘加载quote失败.");
260 | return false;
261 | }
262 | }
263 | return true;
264 | }
265 |
266 | public bool Save(int tradingday)
267 | {
268 | // 这里会被两处地方调用,一个是Disconnect,二是OnDisconnect
269 | // 一个是主动发起,另一个是被动触发,担心OnDisconnect在有些API下不会触发,在退出时保存两次也无所谓
270 |
271 | // 比如没有登录成功,就收到断开消息,这里是会出现交易日为0,这种情况下不保存
272 | if (tradingday == 0)
273 | return false;
274 |
275 | lock (this)
276 | {
277 | try
278 | {
279 | //c.k(string.Format(@"`:{0}{1}/{1}/ set .Q.en[`:{0}{1}/] {2}", Path, "trade", "trade"));
280 | //c.k(string.Format(@"`:{0}{1}/{1}/ set .Q.en[`:{0}{1}/] {2}", Path, "quote", "quote"));
281 | c.k(string.Format(@"`:{0}/{1}/{2} set {3}", Path, "trades", tradingday, "trade"));
282 | Log.Info("保存 trade 表 {0} 完成.", tradingday);
283 | if (SaveQuote)
284 | {
285 | c.k(string.Format(@"`:{0}/{1}/{2} set {3}", Path, "quotes", tradingday, "quote"));
286 | Log.Info("保存 quote 表 {0} 完成.", tradingday);
287 | }
288 | return true;
289 | }
290 | catch (Exception e)
291 | {
292 | Log.Error("保存trade/quote表失败.");
293 | }
294 | }
295 | return false;
296 | }
297 |
298 | public void Disconnect()
299 | {
300 | // 一定要保证退出时要运行
301 | if (null == c)
302 | return;
303 |
304 | lock (this)
305 | {
306 | Save(GetKdbTradingDay());
307 | c.Close();
308 | c = null;
309 | }
310 | }
311 |
312 | public void Write(ref DepthMarketDataNClass pDepthMarketData)
313 | {
314 | // 如果盘中不小心把服务端关了也不再开启
315 | if (null == c)
316 | return;
317 |
318 | string dateTime = pDepthMarketData.ExchangeDateTime().ToString("yyyy.MM.ddTHH:mm:ss.fff");
319 | string symbol = pDepthMarketData.InstrumentID;
320 | double price = pDepthMarketData.LastPrice;
321 | long volume = (long)(pDepthMarketData.Volume);
322 | long openint = (long)(pDepthMarketData.OpenInterest);
323 |
324 | double bid = 0;
325 | double ask = 0;
326 | int bsize = 0;
327 | int asize = 0;
328 |
329 | string trade_str = string.Format("`trade insert({0};`$\"{1}\";{2}f;{3}j;{4}j)", dateTime, symbol, price, volume, openint);
330 | string quote_str = null;
331 |
332 | if (SaveQuote)
333 | {
334 | if (pDepthMarketData.Bids.Length > 0)
335 | {
336 | bid = pDepthMarketData.Bids[0].Price;
337 | bsize = pDepthMarketData.Bids[0].Size;
338 | }
339 | if (pDepthMarketData.Asks.Length > 0)
340 | {
341 | ask = pDepthMarketData.Asks[0].Price;
342 | asize = pDepthMarketData.Asks[0].Size;
343 | }
344 | quote_str = string.Format("`quote insert({0};`$\"{1}\";{2}f;{3}f;{4};{5})", dateTime, symbol, bid, ask, bsize, asize);
345 | }
346 |
347 | // 有一个问题
348 | lock (this)
349 | {
350 | try
351 | {
352 | // trade
353 | c.ks(trade_str);
354 |
355 | // quote
356 | if (SaveQuote)
357 | {
358 | c.ks(quote_str);
359 | }
360 | }
361 | catch (Exception e)
362 | {
363 | // 保存失败,通常是因为网络断开了
364 | Log.Error(e.Message);
365 | c.Close();
366 | c = null;
367 | }
368 | }
369 | }
370 | }
371 | }
372 |
--------------------------------------------------------------------------------
/DataReceiver/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | using XAPI;
8 | using XAPI.Callback;
9 | using QuantBox.Data.Serializer.V2;
10 | using System.IO;
11 | using Newtonsoft.Json;
12 | using System.Text.RegularExpressions;
13 | using System.Configuration;
14 | using NLog;
15 | using System.Runtime.InteropServices;
16 |
17 | namespace DataReceiver
18 | {
19 | ///
20 | /// 需求如下,登录成功后,自动更新合约列表
21 | /// 自动订阅行情,订阅成功后,自动保存行情
22 | /// 订阅时需要进行一下区分,比如说
23 | ///
24 | class Program
25 | {
26 | private const int MF_BYCOMMAND = 0x00000000;
27 | public const int SC_CLOSE = 0xF060;
28 |
29 | [DllImport("user32.dll")]
30 | public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);// 删除菜单
31 |
32 | [DllImport("user32.dll")]
33 | private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);// 获取系统菜单句柄
34 |
35 | [DllImport("kernel32.dll", ExactSpelling = true)]
36 | private static extern IntPtr GetConsoleWindow();// 获取控制台窗口句柄
37 |
38 |
39 | public const string KEY_OutputFormat = "OutputFormat";
40 | public const string KEY_DataPath = "DataPath";
41 | public const string KEY_ConfigPath = "ConfigPath";
42 |
43 | public const string KEY_ConnectionConfigListFileName = "ConnectionConfigListFileName";
44 | public const string KEY_InstrumentInfoListFileName = "InstrumentInfoListFileName";
45 | public const string KEY_IncludeFilterListFileName = "IncludeFilterListFileName";
46 | public const string KEY_ExcludeFilterListFileName = "ExcludeFilterListFileName";
47 |
48 | public const string KEY_SaveAsFilteredInstrumentInfoListFileName = @"SaveAsFilteredInstrumentInfoListFileName";
49 | public const string KEY_SaveAsSubscribedInstrumentInfoListFileName = @"SaveAsSubscribedInstrumentInfoListFileName";
50 | public const string KEY_SaveAsTradingDayFileName = @"SaveAsTradingDayFileName";
51 |
52 | public const string KEY_ScheduleTasksListFileName = "ScheduleTasksListFileName";
53 |
54 | public const string KEY_Kdb_Enable = "Kdb_Enable";
55 | public const string KEY_Kdb_DataPath = "Kdb_DataPath";
56 | public const string KEY_Kdb_Host = "Kdb_Host";
57 | public const string KEY_Kdb_Port = "Kdb_Port";
58 | public const string KEY_Kdb_UsernameAndPassword = "Kdb_UsernameAndPassword";
59 | public const string KEY_Kdb_Save_Quote = "Kdb_Save_Quote";
60 |
61 | static void Main(string[] args)
62 | {
63 | // 禁用控制台的关闭按钮
64 | DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_CLOSE, MF_BYCOMMAND);
65 |
66 | DRTickWriter TickWriter = new DRTickWriter(
67 | ConfigurationManager.AppSettings[KEY_DataPath],
68 | ConfigurationManager.AppSettings[KEY_OutputFormat]
69 | );
70 |
71 | Tom.Kdb.KdbWriter KdbWriter = new Tom.Kdb.KdbWriter(
72 | ConfigurationManager.AppSettings[KEY_Kdb_Host],
73 | ConfigurationManager.AppSettings[KEY_Kdb_Port],
74 | ConfigurationManager.AppSettings[KEY_Kdb_UsernameAndPassword],
75 | ConfigurationManager.AppSettings[KEY_Kdb_DataPath],
76 | ConfigurationManager.AppSettings[KEY_Kdb_Save_Quote]
77 | );
78 |
79 | DataReceiver dataReceiver = new DataReceiver();
80 | dataReceiver.TickWriter = TickWriter;
81 | if(bool.Parse(ConfigurationManager.AppSettings[KEY_Kdb_Enable]))
82 | {
83 | dataReceiver.KdbWriter = KdbWriter;
84 | }
85 |
86 |
87 |
88 | dataReceiver.ConfigPath = ConfigurationManager.AppSettings[KEY_ConfigPath];
89 | dataReceiver.DataPath = ConfigurationManager.AppSettings[KEY_DataPath];
90 | dataReceiver.ConnectionConfigListFileName = ConfigurationManager.AppSettings[KEY_ConnectionConfigListFileName];
91 | dataReceiver.InstrumentInfoListFileName = ConfigurationManager.AppSettings[KEY_InstrumentInfoListFileName];
92 | dataReceiver.IncludeFilterListFileName = ConfigurationManager.AppSettings[KEY_IncludeFilterListFileName];
93 | dataReceiver.ExcludeFilterListFileName = ConfigurationManager.AppSettings[KEY_ExcludeFilterListFileName];
94 |
95 | dataReceiver.SaveAsFilteredInstrumentInfoListFileName = ConfigurationManager.AppSettings[KEY_SaveAsFilteredInstrumentInfoListFileName];
96 | dataReceiver.SaveAsSubscribedInstrumentInfoListFileName = ConfigurationManager.AppSettings[KEY_SaveAsSubscribedInstrumentInfoListFileName];
97 | dataReceiver.SaveAsTradingDayFileName = ConfigurationManager.AppSettings[KEY_SaveAsTradingDayFileName];
98 |
99 | dataReceiver.ScheduleTasksListFileName = ConfigurationManager.AppSettings[KEY_ScheduleTasksListFileName];
100 |
101 | dataReceiver.LoadConnectionConfig();
102 | dataReceiver.Connect();
103 |
104 | // 由于会建立多个,所以超时时间可以长一些
105 | if (dataReceiver.WaitConnectd(30 * 1000))
106 | {
107 | // 可以在这里加入一些订阅前的准备工作
108 | // 这里已经登录成功了,并获得了交易日时间,所以可以用来做别的工作
109 | dataReceiver.BeforeSubscribe();
110 |
111 | dataReceiver.WatcherStrat(dataReceiver.ConfigPath, "*.json");
112 | // 监控配置文件
113 | dataReceiver.ProcessConfig(null);
114 | dataReceiver.ProcessScheduleTasks(null);
115 | Console.WriteLine("开始接收,按Ctrl+Q退出");
116 | }
117 | else
118 | {
119 | Console.WriteLine("登录超时,按Ctrl+Q退出");
120 | }
121 |
122 | do
123 | {
124 | ConsoleKeyInfo cki = Console.ReadKey();
125 | Console.WriteLine(cki);
126 | if (cki.Key == ConsoleKey.Q && cki.Modifiers == ConsoleModifiers.Control)
127 | break;
128 | }while(true);
129 |
130 |
131 | dataReceiver.WatcherStop();
132 | dataReceiver.Disconnect();
133 | Console.WriteLine("按任意键退出");
134 | Console.ReadKey();
135 |
136 | return;
137 | }
138 | }
139 | }
--------------------------------------------------------------------------------
/DataReceiver/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("DataReceiver")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("DataReceiver")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("71bffdb6-39be-49a7-b1ff-68c9f2c2ec29")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/DataReceiver/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.34014
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DataReceiver.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DataReceiver.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/DataReceiver/Properties/Resources.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 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/DataReceiver/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.34014
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DataReceiver.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/DataReceiver/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/DataReceiver/Struct.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using Newtonsoft.Json;
7 | using XAPI;
8 | using System.Runtime.Serialization.Json;
9 | using System.Runtime.Serialization;
10 |
11 | namespace DataReceiver
12 | {
13 | //
14 | /// 连接配置信息
15 | ///
16 | [DataContract]
17 | public class ConnectionConfig
18 | {
19 | ///
20 | /// dll地址
21 | ///
22 | [DataMember(Order = 0)]
23 | public string LibPath;
24 | ///
25 | /// 服务器
26 | ///
27 | [DataMember(Order = 1)]
28 | public ServerInfoField Server;
29 | ///
30 | /// 账号
31 | ///
32 | [DataMember(Order = 2)]
33 | public UserInfoField User;
34 | ///
35 | /// 同一服务器和账号最大可登录会话数
36 | ///
37 | [DataMember(Order = 3)]
38 | public int SessionLimit;
39 | ///
40 | /// 每个会话最大可订阅数
41 | ///
42 | [DataMember(Order = 4)]
43 | public int SubscribePerSession;
44 | }
45 |
46 | ///
47 | /// 查询得到的合约信息
48 | ///
49 | public class InstrumentInfo
50 | {
51 | public string Symbol;
52 | public string Instrument;
53 | public string Exchange;
54 | public string ProductID;
55 | public double TickSize;
56 | public double Factor;
57 | [JsonIgnore]
58 | public int Time_ssf_Diff;
59 |
60 | public override bool Equals(object obj)
61 | {
62 | if (obj is InstrumentInfo)
63 | return this.GetHashCode().Equals(((InstrumentInfo)obj).GetHashCode());
64 | else return false;
65 | }
66 |
67 | public override int GetHashCode()
68 | {
69 | int hashID = Instrument.GetHashCode();
70 | int hashValue = Exchange.GetHashCode();
71 | return hashID ^ hashValue;
72 | }
73 | }
74 |
75 | ///
76 | /// 写文件时要用到的信息,有了此文件可以进行文件大小的优化
77 | /// 同时
78 | ///
79 | public class InstrumentFilterConfig
80 | {
81 | public string SymbolRegex;
82 | ///
83 | /// 只是为了节省文件大小
84 | ///
85 | public int Time_ssf_Diff;
86 | }
87 |
88 | ///
89 | /// 本来是用的tuple,但没办法用微软内置的转成json,只好自己定义一个
90 | ///
91 | [DataContract]
92 | public class ScheduleTaskConfig
93 | {
94 | [DataMember(Order = 0)]
95 | public TimeSpan Item1;
96 | [DataMember(Order = 1)]
97 | public string Item2;
98 | [DataMember(Order = 2)]
99 | public string Item3;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/DataReceiver/WatcherTimer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.IO;
7 |
8 | namespace FileMonitor
9 | {
10 |
11 | public class WatcherTimer
12 | {
13 | private int TimeoutMillis = 2000;
14 |
15 | System.IO.FileSystemWatcher fsw = new System.IO.FileSystemWatcher();
16 | System.Threading.Timer m_timer = null;
17 | List files = new List();
18 | FileSystemEventHandler fswHandler = null;
19 |
20 | public WatcherTimer(FileSystemEventHandler watchHandler)
21 | {
22 | m_timer = new System.Threading.Timer(new TimerCallback(OnTimer), null, Timeout.Infinite, Timeout.Infinite);
23 | fswHandler = watchHandler;
24 | }
25 |
26 |
27 | public WatcherTimer(FileSystemEventHandler watchHandler, int timerInterval)
28 | {
29 | m_timer = new System.Threading.Timer(new TimerCallback(OnTimer), null, Timeout.Infinite, Timeout.Infinite);
30 | TimeoutMillis = timerInterval;
31 | fswHandler = watchHandler;
32 | }
33 |
34 | public void OnFileChanged(object sender, FileSystemEventArgs e)
35 | {
36 | //MessageBox.Show("Created", "Create triggered");
37 | Mutex mutex = new Mutex(false, "FSW");
38 | mutex.WaitOne();
39 | if (!files.Contains(e.Name))
40 | {
41 | files.Add(e.Name);
42 | }
43 | mutex.ReleaseMutex();
44 |
45 | m_timer.Change(TimeoutMillis, Timeout.Infinite);
46 | }
47 |
48 | private void OnTimer(object state)
49 | {
50 | List backup = new List();
51 |
52 | Mutex mutex = new Mutex(false, "FSW");
53 | mutex.WaitOne();
54 | backup.AddRange(files);
55 | files.Clear();
56 | mutex.ReleaseMutex();
57 |
58 |
59 | foreach (string file in backup)
60 | {
61 | fswHandler(this, new FileSystemEventArgs(WatcherChangeTypes.Changed, string.Empty, file));
62 | }
63 | }
64 |
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/DataReceiver/XAPI_Extensions.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using XAPI.Callback;
8 |
9 | namespace DataReceiver
10 | {
11 | public static class XAPI_Extensions
12 | {
13 | public static Logger GetLog(this XApi api)
14 | {
15 | return (api.Log as Logger);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/DataReceiver/c.cs:
--------------------------------------------------------------------------------
1 | //2017.05.23 identify string[] as type 11
2 | //2017.04.18 added ssl/tls support
3 | //2014.01.29 make method n public
4 | //2013.12.19 qn did not detect null guid
5 | //2013.12.10 remove retry logic on authentication fail. For kdb+2.5 and prior, use
6 | // B=new byte[1+u.Length];Connect(h,p);s=this.GetStream();J=0;w(u);s.Write(B,0,J);if(1!=s.Read(B,0,1))...
7 | //2013.09.16 za represents -0Wd, not 0Nd
8 | //2013.08.20 null val for TimeStamp -> nj
9 | //2012.06.07 fixed scoping of GUID
10 | //2012.05.29 for use with kdb+v3.0, changed handshake and added Guid. boolean v6->vt tracks type capability.
11 | //2012.01.26 refactored clamp into clampDT, for Date.DateTime()
12 | //2012.01.25 rz() clamp datetime to valid range
13 | //2010.11.17 Block sending new timetypes to version of kdb+ prior to v2.6 (use prior release of c.cs for older kdb+ versions)
14 | // Max buffer size (default 64kB) used for reading is now a parameter to the c constructor
15 | // Date, Month, Minute, Second, KTimeSpan are now serializable, implement IComparable
16 | // and have default constructors for xml serialization.
17 | // Added NULL(Type t)
18 | //2010.08.05 Added KException for exceptions due to server error, authentication fail and func decode
19 | //2010.01.14 Exposed static var e (Encoding) as public
20 | //2010.01.12 Added support for unicode encoding, defaults to ASCII
21 | //2010.01.11 Added null checks for qn for UDTs Date,Month,Minute,Second,KTimespan
22 | //2010.01.04 Added new time types (timespan->KTimespan,timestamp->DateTime), drop writing kdb+ datetime
23 | //2009.10.19 Limit reads to blocks of 64kB to reduce load on kernel memory
24 | //2007.09.26 0Wz to MaxValue
25 | //2006.10.05 truncate string at null
26 | //2006.09.29 NULL c.Date class(sync with c.java)
27 | //Regarding SSL/TLS: To use self-signed certificates add them to the Local Computer Trusted Root Certification Authorities
28 | using System;
29 | using System.IO;
30 | using System.Net.Sockets;
31 | using System.Net.Security;
32 | using System.Security.Cryptography.X509Certificates;
33 | namespace kx{
34 | public class c:TcpClient{
35 | /*public static void Main(string[]args){
36 | //c.ReceiveTimeout=1000;
37 | //c c=new c("localhost",5010);c.k(".u.sub[`trade;`MSFT.O`IBM.N]");while(true){object r=c.k();O(n(at(r,2)));}
38 | c c=new c("localhost",5001);
39 | //c.e=System.Text.Encoding.UTF8;
40 | //O("Unicode "+c.k("`$\"c\"$0x52616e627920426ac3b6726b6c756e64204142"));
41 | //object[]x=new object[4];x[0]=t();x[1]="xx";x[2]=(double)93.5;x[3]=300;tm();for(int i=0;i<1000;++i)c.k("insert","trade",x);tm();
42 | //Flip r=td(c.k("select sum price by sym from trade"));O("cols: "+n(r.x));O("rows: "+n(r.y[0]));
43 | c.Close();
44 | }
45 | */
46 | private const int DefaultMaxBufferSize=65536;
47 | private readonly int _maxBufferSize=DefaultMaxBufferSize;
48 | public static System.Text.Encoding e=System.Text.Encoding.ASCII;
49 | byte[]b,B;int j,J,vt;bool a;Stream s;public new void Close(){s.Close();base.Close();}
50 | public c(string h,int p):this(h,p,Environment.UserName){}
51 | public c(string h,int p,string u,int maxBufferSize=DefaultMaxBufferSize,bool useTLS=false){_maxBufferSize=maxBufferSize;Connect(h,p);s=this.GetStream();if(useTLS){s=new SslStream(s,false);((SslStream)s).AuthenticateAsClient(h);}B=new byte[2+u.Length];J=0;w(u+"\x3");s.Write(B,0,J);if(1!=s.Read(B,0,1))throw new KException("access");vt=Math.Min(B[0],(byte)3);}
52 | static int ns(string s){int i=s.IndexOf('\0');i=-14)&&x.Equals(NU[t]);}
61 | private void u(){int n=0,r=0,f=0,s=8,p=s;short i=0;j=0;byte[]dst=new byte[ri()];int d=j;int[]aa=new int[256];
62 | while(s>8);}short rh(){int x=b[j++],y=b[j++];return(short)(a?x&0xff|y<<8:x<<8|y&0xff);}
113 | void w(int i){w((short)i);w((short)(i>>16));}int ri(){int x=rh(),y=rh();return a?x&0xffff|y<<16:x<<16|y&0xffff;}
114 | private byte[]gip={3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
115 | void w(Guid g){byte[]b=g.ToByteArray();if(vt<3)throw new KException("Guid not valid pre kdb+3.0");for(int i=0;i>32));}long rj(){int x=ri(),y=ri();return a?x&0xffffffffL|(long)y<<32:(long)x<<32|y&0xffffffffL;}
118 | void w(float e){byte[]b=BitConverter.GetBytes(e);foreach(byte i in b)w(i);}float re(){byte c;float e;
119 | if(!a){c=b[j];b[j]=b[j+3];b[j+3]=c;c=b[j+1];b[j+1]=b[j+2];b[j+2]=c;}e=BitConverter.ToSingle(b,j);j+=4;return e;}
120 | void w(double f){w(BitConverter.DoubleToInt64Bits(f));}double rf(){return BitConverter.Int64BitsToDouble(rj());}
121 | void w(char c){w((byte)c);}char rc(){return (char)(b[j++]&0xff);}
122 | void w(string s){byte[]b=e.GetBytes(s);foreach(byte i in b)w(i);B[J++]=0;}
123 | string rs(){int k=j;for(;b[j]!=0;++j);string s=e.GetString(b,k,j-k);j++;return s;}
124 | void w(Date d){w(d.i);}Date rd(){return new Date(ri());} void w(Minute u){w(u.i);}Minute ru(){return new Minute(ri());}
125 | void w(Month m){w(m.i);}Month rm(){return new Month(ri());}void w(Second v){w(v.i);}Second rv(){return new Second(ri());}
126 | void w(TimeSpan t){if(vt<1)throw new KException("Timespan not valid pre kdb+2.6");w(qn(t)?ni:(int)(t.Ticks/10000));}TimeSpan rt(){int i=ri();return new TimeSpan(qn(i)?nj:10000L*i);}
127 | void w(DateTime p){if(vt<1)throw new KException("Timestamp not valid pre kdb+2.6");w(qn(p)?nj:(100*(p.Ticks-o)));}
128 | DateTime rz(){double f=rf();return Double.IsInfinity(f)?(f<0?za:zw):new DateTime(qn(f)?0:clampDT(10000*(long)Math.Round(8.64e7*f)+o));}
129 | void w(KTimespan t){w(qn(t)?nj:(t.t.Ticks*100));} KTimespan rn(){return new KTimespan(rj());}
130 | DateTime rp(){long j=rj(),d=j<0?(j+1)/100-1:j/100;DateTime p=new DateTime(j==nj?0:o+d);return p;}
131 | void w(object x){int t=c.t(x);w((byte)t);if(t<0)switch(t){case-1:w((bool)x);return;
132 | case-2:w((Guid)x);return;case-4:w((byte)x);return;
133 | case-5:w((short)x);return;case-6:w((int)x);return;case-7:w((long)x);return;case-8:w((float)x);return;case-9:w((double)x);return;
134 | case-10:w((char)x);return;case-11:w((string)x);return;case-12:w((DateTime)x);return;case-13:w((Month)x);return;
135 | case-14:w((Date)x);return;case-15:w((DateTime)x);return;case-16:w((KTimespan)x);return;case-17:w((Minute)x);return;case-18:w((Second)x);return;
136 | case-19:w((TimeSpan)x);return;}
137 | if(t==99){Dict r=(Dict)x;w(r.x);w(r.y);return;}B[J++]=0;if(t==98){Flip r=(Flip)x;B[J++]=99;w(r.x);w(r.y);return;}
138 | w(c.n(x));switch(t){
139 | case 0:foreach(object o in(object[])x)w(o);return; case 1:foreach(bool o in(bool[])x)w(o);return;
140 | case 2:foreach(Guid o in(Guid[])x)w(o);return;
141 | case 4:foreach(byte o in(byte[])x)w(o);return; case 5:foreach(short o in(short[])x)w(o);return;
142 | case 6:foreach(int o in(int[])x)w(o);return; case 7:foreach(long o in(long[])x)w(o);return;
143 | case 8:foreach(float o in(float[])x)w(o);return; case 9:foreach(double o in(double[])x)w(o);return;
144 | case 10:foreach(byte b in e.GetBytes((char[])x))w(b);return; case 11:foreach(string o in(string[])x)w(o);return;
145 | case 12:foreach(DateTime o in(DateTime[])x)w(o);return; case 13:foreach(Month o in(Month[])x)w(o);return;
146 | case 14:foreach(Date o in(Date[])x)w(o);return; case 15:foreach(DateTime o in(DateTime[])x)w(o);return;
147 | case 16:foreach(KTimespan o in(KTimespan[])x)w(o);return; case 17:foreach(Minute o in(Minute[])x)w(o);return;
148 | case 18:foreach(Second o in(Second[])x)w(o);return; case 19:foreach(TimeSpan o in(TimeSpan[])x)w(o);return;}
149 | }
150 | object r(){int i=0,n,t=(sbyte)b[j++];if(t<0)switch(t){case-1:return rb();case-2:return rg();case-4:return b[j++]; case-5:return rh();
151 | case-6:return ri();case-7:return rj();case-8:return re();case-9:return rf();case-10:return rc();case-11:return rs();
152 | case -12: return rp();case-13:return rm();case-14:return rd();case-15:return rz();case -16:return rn();case-17:return ru();
153 | case-18:return rv();case-19:return rt();}
154 | if(t>99){if(t==101&&b[j++]==0)return null;throw new KException("func");}if(t==99)return new Dict(r(),r());j++;if(t==98)return new Flip((Dict)r());n=ri();switch(t){
155 | case 0:object[]L=new object[n];for(;i
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/DataReceiver使用手册.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/DataReceiver使用手册.docx
--------------------------------------------------------------------------------
/GetInstruments/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/GetInstruments/GetInstruments.cs:
--------------------------------------------------------------------------------
1 | using DataReceiver;
2 | using NLog;
3 | using XAPI;
4 | using XAPI.Callback;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace GetInstruments
12 | {
13 | ///
14 | /// 登录得到最新的合约列表
15 | ///
16 | public class GetInstruments : ApiBase
17 | {
18 | public string ConnectionConfigFileName = @"ConnectionConfig.json";
19 |
20 | public ConnectionConfig ConnectionConfig;
21 |
22 | public void Save()
23 | {
24 | // 连接信息没有必要重新保存
25 | //Save(ConfigPath, ConnectionConfigFileName, ConnectionConfig);
26 | Save(ConfigPath, InstrumentInfoListFileName, InstrumentInfoList);
27 | }
28 |
29 | public void Load()
30 | {
31 | ConnectionConfig = new ConnectionConfig();
32 | InstrumentInfoList = new List();
33 |
34 | ConnectionConfig = (ConnectionConfig)Load(ConfigPath, ConnectionConfigFileName, ConnectionConfig);
35 | InstrumentInfoList = (List)Load(ConfigPath, InstrumentInfoListFileName, InstrumentInfoList);
36 |
37 | if (ConnectionConfig == null)
38 | ConnectionConfig = new ConnectionConfig();
39 | if (InstrumentInfoList == null)
40 | InstrumentInfoList = new List();
41 | }
42 |
43 | public void Connect()
44 | {
45 | XApi api = new XApi(ConnectionConfig.LibPath);
46 |
47 | api.Server = ConnectionConfig.Server;
48 | api.User = ConnectionConfig.User;
49 |
50 | api.Log = LogManager.GetLogger(string.Format("{0}.{1}", api.Server.BrokerID, api.User.UserID));
51 | api.MaxSubscribedInstrumentsCount = ConnectionConfig.SubscribePerSession;
52 |
53 | api.OnConnectionStatus = OnConnectionStatus;
54 | api.OnRspQryInstrument = OnRspQryInstrument;
55 |
56 | api.Connect();
57 |
58 | XApiList.Add(api);
59 | }
60 |
61 | public void ReqQryInstrument()
62 | {
63 | bIsLast = false;
64 | InstrumentInfoList.Clear();
65 |
66 | foreach (var api in XApiList)
67 | {
68 | ReqQueryField query = default(ReqQueryField);
69 | api.ReqQuery(QueryType.ReqQryInstrument, ref query);
70 | }
71 | }
72 |
73 | private void OnRspQryInstrument(object sender, ref InstrumentField instrument, int size1, bool bIsLast)
74 | {
75 | if (size1 > 0)
76 | {
77 | InstrumentInfoList.Add(new InstrumentInfo()
78 | {
79 | Symbol = instrument.Symbol,
80 | Instrument = instrument.InstrumentID,
81 | Exchange = instrument.ExchangeID,
82 | ProductID = instrument.ProductID,
83 | TickSize = instrument.PriceTick,
84 | Factor = instrument.VolumeMultiple
85 | });
86 | }
87 |
88 | this.bIsLast = bIsLast;
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/GetInstruments/GetInstruments.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7D847C1F-C052-47ED-AA52-3827ECEF29B9}
8 | Exe
9 | Properties
10 | GetInstruments
11 | GetInstruments
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | ..\bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 | ..\packages\NLog.4.4.12\lib\net45\NLog.dll
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ..\lib\XAPI_CSharp.exe
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | {9e58b4e4-342b-483a-bb7f-f89a52ef7cbf}
68 | DataReceiver
69 |
70 |
71 |
72 |
73 |
74 | if not exist "$(TargetDir)bin32" md "$(TargetDir)bin32"
75 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin32\*.*" "$(TargetDir)bin32"
76 | if not exist "$(TargetDir)bin64" md "$(TargetDir)bin64"
77 | xcopy /s /y "$(SolutionDir)packages\HDF.PInvoke.1.10.0.4\lib\native\bin64\*.*" "$(TargetDir)bin64"
78 |
79 |
86 |
--------------------------------------------------------------------------------
/GetInstruments/Program.cs:
--------------------------------------------------------------------------------
1 | using NLog;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Configuration;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows.Forms;
8 |
9 | namespace GetInstruments
10 | {
11 | ///
12 | /// 由计划任务启动
13 | /// 每天晚上9点前启动,每天早上9点前也启动
14 | /// 如果登录失败等情况,就不更新合约列表文件
15 | /// 运行完就退出
16 | ///
17 | class Program
18 | {
19 | public const string KEY_ConfigPath = "ConfigPath";
20 |
21 | public const string KEY_ConnectionConfigFileName = "ConnectionConfigFileName";
22 | public const string KEY_InstrumentInfoListFileName = "InstrumentInfoListFileName";
23 |
24 | static void Main(string[] args)
25 | {
26 | Logger Log = LogManager.GetCurrentClassLogger();
27 |
28 | GetInstruments GetInstruments = null;
29 | for (int i = 1; i <= 3; ++i)
30 | {
31 | GetInstruments = new GetInstruments();
32 | GetInstruments.ConfigPath = ConfigurationManager.AppSettings[KEY_ConfigPath];
33 | GetInstruments.ConnectionConfigFileName = ConfigurationManager.AppSettings[KEY_ConnectionConfigFileName];
34 | GetInstruments.InstrumentInfoListFileName = ConfigurationManager.AppSettings[KEY_InstrumentInfoListFileName];
35 | GetInstruments.Load();
36 | GetInstruments.Connect();
37 | // 改这么大主要是金仕达接口太不给力
38 | if (!GetInstruments.WaitConnectd(30 * 1000))
39 | {
40 | Log.Info("连接超时,第{0}次", i);
41 | GetInstruments.Disconnect();
42 | GetInstruments = null;
43 | }
44 | else
45 | {
46 | break;
47 | }
48 | }
49 |
50 | if (GetInstruments == null)
51 | {
52 | Log.Info("连接超时多次,退出");
53 | return;
54 | }
55 |
56 | GetInstruments.ReqQryInstrument();
57 | // 这个超时是否过短?因为在LTS模拟中可能要5分钟
58 | if(GetInstruments.WaitIsLast(60*1000))
59 | {
60 | Log.Info("一共查询到 {0} 条合约", GetInstruments.InstrumentInfoList.Count);
61 | if(GetInstruments.InstrumentInfoList.Count>0)
62 | {
63 | GetInstruments.Save();
64 | Log.Info("另存合约列表到 {0}", GetInstruments.InstrumentInfoListFileName);
65 | }
66 | }
67 | else
68 | {
69 | Log.Info("查询合约超时");
70 | }
71 |
72 | GetInstruments.Disconnect();
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/GetInstruments/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("GetInstruments")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("GetInstruments")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("dadd18e7-b382-4111-b298-baea725d100d")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/GetInstruments/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/QuantBox.DataReceiver.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}") = "GetInstruments", "GetInstruments\GetInstruments.csproj", "{7D847C1F-C052-47ED-AA52-3827ECEF29B9}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchiveData", "ArchiveData\ArchiveData.csproj", "{C03DE914-AB11-4FE3-B44F-DF2260280561}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataReceiver", "DataReceiver\DataReceiver.csproj", "{9E58B4E4-342B-483A-BB7F-F89A52EF7CBF}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataDownload", "DataDownload\DataDownload.csproj", "{529AAC14-B1FF-4524-929D-40756CAB260B}"
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 | {7D847C1F-C052-47ED-AA52-3827ECEF29B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {7D847C1F-C052-47ED-AA52-3827ECEF29B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {7D847C1F-C052-47ED-AA52-3827ECEF29B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {7D847C1F-C052-47ED-AA52-3827ECEF29B9}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {C03DE914-AB11-4FE3-B44F-DF2260280561}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {C03DE914-AB11-4FE3-B44F-DF2260280561}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {C03DE914-AB11-4FE3-B44F-DF2260280561}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {C03DE914-AB11-4FE3-B44F-DF2260280561}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {9E58B4E4-342B-483A-BB7F-F89A52EF7CBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {9E58B4E4-342B-483A-BB7F-F89A52EF7CBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {9E58B4E4-342B-483A-BB7F-F89A52EF7CBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {9E58B4E4-342B-483A-BB7F-F89A52EF7CBF}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {529AAC14-B1FF-4524-929D-40756CAB260B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {529AAC14-B1FF-4524-929D-40756CAB260B}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {529AAC14-B1FF-4524-929D-40756CAB260B}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {529AAC14-B1FF-4524-929D-40756CAB260B}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DataReceiver 行情接收器
2 |
3 | ##介绍
4 | 1. 行情接收器,目前需要自行编译,test.zip中是测试用的配置文件
5 | 2. 支持归档时存为h5格式,提供给Python和MATLAB使用
6 | 3. demo下为读取h5格式的示例
7 |
--------------------------------------------------------------------------------
/clear.bat:
--------------------------------------------------------------------------------
1 | rd ArchiveData\bin /S /Q
2 | rd ArchiveData\obj /S /Q
3 | rd DataReceiver\bin /S /Q
4 | rd DataReceiver\obj /S /Q
5 | rd GetInstruments\bin /S /Q
6 | rd GetInstruments\obj /S /Q
7 | rd DataDownload\bin /S /Q
8 | rd DataDownload\obj /S /Q
--------------------------------------------------------------------------------
/demo/read_hdf5.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/demo/read_hdf5.m
--------------------------------------------------------------------------------
/demo/read_hdf5.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | ################
4 | # 使用pandas来读取
5 | import pandas as pd
6 | df1 = pd.read_hdf(r'test.h5','IF1509_20150202')
7 | df1.dtypes
8 |
9 | ################
10 | # 使用h5py来读取
11 | import h5py
12 | f = h5py.File(r'test.h5', 'a')
13 |
14 | # 打印表名
15 | for name in f:
16 | print(name)
17 |
18 | ds = f['IF1509_20150202'][:]
19 |
20 | df2 = pd.DataFrame(ds)
21 | df2.dtypes
22 |
23 | ################
24 | # 时间处理,可看情况是否加入毫秒
25 | import numpy as np
26 | df2['datetime'] = df2['ActionDay'].astype(np.int64)*1000000+df2['UpdateTime']
27 |
28 |
--------------------------------------------------------------------------------
/demo/test.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/demo/test.h5
--------------------------------------------------------------------------------
/lib/QuantBox.Data.Serializer.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/lib/QuantBox.Data.Serializer.dll
--------------------------------------------------------------------------------
/lib/XAPI_CSharp.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/lib/XAPI_CSharp.exe
--------------------------------------------------------------------------------
/lib/protobuf-net.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/lib/protobuf-net.dll
--------------------------------------------------------------------------------
/php.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/php.zip
--------------------------------------------------------------------------------
/test.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuantBox/QuantBox.DataReceiver/1187b76bfe1683de52f75a76b7da9d5589e2aaea/test.zip
--------------------------------------------------------------------------------