├── .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 --------------------------------------------------------------------------------