diff --git a/Demo/OpenQuant.API.chm b/Demo/OpenQuant.API.chm new file mode 100644 index 0000000..b685158 Binary files /dev/null and b/Demo/OpenQuant.API.chm differ diff --git a/Demo/OpenQuant.API.chw b/Demo/OpenQuant.API.chw new file mode 100644 index 0000000..cdcc2db Binary files /dev/null and b/Demo/OpenQuant.API.chw differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.obj b/Demo/QuantBox.OQ.Demo.CLI/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.obj new file mode 100644 index 0000000..4cd0c8d Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/.NETFramework,Version=v4.5.AssemblyAttributes.obj differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/AssemblyInfo.obj b/Demo/QuantBox.OQ.Demo.CLI/Debug/AssemblyInfo.obj new file mode 100644 index 0000000..0bf6d91 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/AssemblyInfo.obj differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/CL.read.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/CL.read.1.tlog new file mode 100644 index 0000000..0f6d88b Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/CL.read.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/CL.write.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/CL.write.1.tlog new file mode 100644 index 0000000..43ed2ba Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/CL.write.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/QuantBox.OQ.Demo.CLI.lastbuildstate b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/QuantBox.OQ.Demo.CLI.lastbuildstate new file mode 100644 index 0000000..74dd8b1 --- /dev/null +++ b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/QuantBox.OQ.Demo.CLI.lastbuildstate @@ -0,0 +1,2 @@ +#TargetFrameworkVersion=v4.5:PlatformToolSet=v120:EnableManagedIncrementalBuild=true:VCToolArchitecture=Native32Bit +Debug|Win32|D:\用户目录\Documents\GitHub\OpenQuant\Demo\| diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/QuantBox.OQ.Demo.CLI.write.1u.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/QuantBox.OQ.Demo.CLI.write.1u.tlog new file mode 100644 index 0000000..0fa69ab Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/QuantBox.OQ.Demo.CLI.write.1u.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/RSAENH.DLL.bi b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/RSAENH.DLL.bi new file mode 100644 index 0000000..e69de29 diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/TZRES.DLL.bi b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/TZRES.DLL.bi new file mode 100644 index 0000000..e69de29 diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/cl.command.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/cl.command.1.tlog new file mode 100644 index 0000000..7c8f1b1 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/cl.command.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.command.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.command.1.tlog new file mode 100644 index 0000000..4af348d Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.command.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.read.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.read.1.tlog new file mode 100644 index 0000000..52024c1 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.read.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.write.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.write.1.tlog new file mode 100644 index 0000000..a435195 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/link.write.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/metagen.read.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/metagen.read.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/metagen.read.1.tlog @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/metagen.write.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/metagen.write.1.tlog new file mode 100644 index 0000000..46b134b --- /dev/null +++ b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/metagen.write.1.tlog @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.command.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.command.1.tlog new file mode 100644 index 0000000..bab415a Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.command.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.read.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.read.1.tlog new file mode 100644 index 0000000..d7b4ca5 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.read.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.write.1.tlog b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.write.1.tlog new file mode 100644 index 0000000..17dac71 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.12BB57A6.tlog/rc.write.1.tlog differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.Build.CppClean.log b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.Build.CppClean.log new file mode 100644 index 0000000..d7a16bb --- /dev/null +++ b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.Build.CppClean.log @@ -0,0 +1,41 @@ +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.oq.demo.cli.pch +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\vc120.pdb +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\stdafx.obj +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.oq.demo.cli.obj +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\assemblyinfo.obj +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\.netframework,version=v4.5.assemblyattributes.obj +c:\program files (x86)\smartquant ltd\openquant\bin\quantbox.oq.demo.cli.dll +c:\program files (x86)\smartquant ltd\openquant\bin\quantbox.oq.demo.cli.pdb +c:\program files (x86)\smartquant ltd\openquant\bin\openquant.api.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.providers.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.instruments.dll +c:\program files (x86)\smartquant ltd\openquant\bin\openquant.objectmap.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.charting.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.series.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.execution.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.data.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.fix.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.quant.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.dll +c:\program files (x86)\smartquant ltd\openquant\bin\openquant.config.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.fixdata.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.file.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.services.dll +c:\program files (x86)\smartquant ltd\openquant\bin\sharpziplib.dll +c:\program files (x86)\smartquant ltd\openquant\bin\smartquant.xml.dll +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\app.res +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.oq.demo.cli.vcxprojresolveassemblyreference.cache +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\cl.command.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\cl.read.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\cl.write.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\link.command.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\link.read.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\link.write.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\metagen.read.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\metagen.write.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\quantbox.oq.demo.cli.write.1u.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\rc.command.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\rc.read.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\rc.write.1.tlog +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\rsaenh.dll.bi +d:\用户目录\documents\github\openquant\demo\quantbox.oq.demo.cli\debug\quantbox.12bb57a6.tlog\tzres.dll.bi diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.log b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.log new file mode 100644 index 0000000..24bcd92 --- /dev/null +++ b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.log @@ -0,0 +1,28 @@ +生成启动时间为 2014/5/10 21:39:45。 + 1>项目“D:\用户目录\Documents\GitHub\OpenQuant\Demo\QuantBox.OQ.Demo.CLI\QuantBox.OQ.Demo.CLI.vcxproj”在节点 2 上(Rebuild 个目标)。 + 1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets(357,5): warning MSB8004: Output Directory does not end with a trailing slash. This build instance will add the slash as it is required to allow proper evaluation of the Output Directory. + 1>ClCompile: + D:\Program Files\Microsoft Visual Studio 12.0\VC\bin\CL.exe /c /AI"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\\" /AI"C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral" /AI"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Facades\\" /Zi /clr /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D _WINDLL /D _UNICODE /D UNICODE /EHa /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yc"stdafx.h" /Fp"Debug\QuantBox.OQ.Demo.CLI.pch" /Fo"Debug\\" /Fd"Debug\vc120.pdb" /TP /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll" /FU"D:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\OpenQuant.API.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Xml.dll" /analyze- /errorReport:prompt /clr:nostdlib Stdafx.cpp + Stdafx.cpp + D:\Program Files\Microsoft Visual Studio 12.0\VC\bin\CL.exe /c /AI"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\\" /AI"C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral" /AI"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Facades\\" /Zi /clr /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D _WINDLL /D _UNICODE /D UNICODE /EHa /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yu"stdafx.h" /Fp"Debug\QuantBox.OQ.Demo.CLI.pch" /Fo"Debug\\" /Fd"Debug\vc120.pdb" /TP /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll" /FU"D:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\OpenQuant.API.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Xml.dll" /analyze- /errorReport:prompt /clr:nostdlib AssemblyInfo.cpp QuantBox.OQ.Demo.CLI.cpp + AssemblyInfo.cpp + 1>AssemblyInfo.cpp(40): warning C4947: “RequestMinimum”: 标记为已过时 + 消息: “Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.” + QuantBox.OQ.Demo.CLI.cpp + 正在生成代码... + D:\Program Files\Microsoft Visual Studio 12.0\VC\bin\CL.exe /c /Zi /clr /nologo /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D _WINDLL /D _UNICODE /D UNICODE /EHa /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Debug\\" /Fd"Debug\vc120.pdb" /TP /analyze- /errorReport:prompt "C:\Users\Administrator\AppData\Local\Temp\.NETFramework,Version=v4.5.AssemblyAttributes.cpp" + .NETFramework,Version=v4.5.AssemblyAttributes.cpp + ResourceCompile: + C:\Program Files (x86)\Windows Kits\8.1\bin\x86\rc.exe /D _UNICODE /D UNICODE /l"0x0409" /nologo /fo"Debug\app.res" app.rc + Link: + D:\Program Files\Microsoft Visual Studio 12.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Demo.CLI.dll" /INCREMENTAL /NOLOGO /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Demo.CLI.pdb" /ASSEMBLYDEBUG /TLBID:1 /DYNAMICBASE /FIXED:NO /NXCOMPAT /MACHINE:X86 /DLL Debug\app.res + Debug\AssemblyInfo.obj + Debug\QuantBox.OQ.Demo.CLI.obj + Debug\Stdafx.obj + "Debug\.NETFramework,Version=v4.5.AssemblyAttributes.obj" + QuantBox.OQ.Demo.CLI.vcxproj -> C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Demo.CLI.dll + 1>已完成生成项目“D:\用户目录\Documents\GitHub\OpenQuant\Demo\QuantBox.OQ.Demo.CLI\QuantBox.OQ.Demo.CLI.vcxproj”(Rebuild 个目标)的操作。 + +生成成功。 + +已用时间 00:00:09.16 diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.vcxprojResolveAssemblyReference.cache b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.vcxprojResolveAssemblyReference.cache new file mode 100644 index 0000000..3bdff4a Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/QuantBox.OQ.Demo.CLI.vcxprojResolveAssemblyReference.cache differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/Stdafx.obj b/Demo/QuantBox.OQ.Demo.CLI/Debug/Stdafx.obj new file mode 100644 index 0000000..b020dc2 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/Stdafx.obj differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/app.res b/Demo/QuantBox.OQ.Demo.CLI/Debug/app.res new file mode 100644 index 0000000..613b1c4 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/app.res differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/Debug/vc120.pdb b/Demo/QuantBox.OQ.Demo.CLI/Debug/vc120.pdb new file mode 100644 index 0000000..b0ed333 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.CLI/Debug/vc120.pdb differ diff --git a/Demo/QuantBox.OQ.Demo.CLI/QuantBox.OQ.Demo.CLI.vcxproj b/Demo/QuantBox.OQ.Demo.CLI/QuantBox.OQ.Demo.CLI.vcxproj index e5fbae2..bea634c 100644 --- a/Demo/QuantBox.OQ.Demo.CLI/QuantBox.OQ.Demo.CLI.vcxproj +++ b/Demo/QuantBox.OQ.Demo.CLI/QuantBox.OQ.Demo.CLI.vcxproj @@ -43,7 +43,7 @@ true - ..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Bin + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin false diff --git a/Demo/QuantBox.OQ.Demo.v12.suo b/Demo/QuantBox.OQ.Demo.v12.suo new file mode 100644 index 0000000..c943717 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo.v12.suo differ diff --git a/Demo/QuantBox.OQ.Demo/Data/DataConvert_code.cs b/Demo/QuantBox.OQ.Demo/Data/DataConvert_code.cs index aed2a22..88a6c90 100644 --- a/Demo/QuantBox.OQ.Demo/Data/DataConvert_code.cs +++ b/Demo/QuantBox.OQ.Demo/Data/DataConvert_code.cs @@ -1,36 +1,36 @@ -using System; -using System.Drawing; - -using OpenQuant.API; -using OpenQuant.API.Indicators; - -using QuantBox.CSharp2CTP; -using QuantBox.Helper.CTP; - -namespace QuantBox.OQ.Demo.Data -{ - public class DataConvert_code:Strategy - { - CThostFtdcDepthMarketDataField DepthMarketData; - - public override void OnTrade(Trade trade) - { - // 插件3.8.2.0 中开始可用,是将Trade数据中的深度数据取出 - if (DataConvert.TryConvert(trade, ref DepthMarketData)) - { - Console.WriteLine("OnTrade " + DepthMarketData.LastPrice); - Console.WriteLine("OnTrade " + DepthMarketData.UpperLimitPrice); - } - } - - public override void OnQuote(Quote quote) - { - // 插件3.8.2.1 中开始可用,是将Quote数据中的深度数据取出 - if (DataConvert.TryConvert(quote, ref DepthMarketData)) - { - Console.WriteLine("OnQuote " + DepthMarketData.LastPrice); - Console.WriteLine("OnQuote " + DepthMarketData.UpperLimitPrice); - } - } - } -} +using System; +using System.Drawing; + +using OpenQuant.API; +using OpenQuant.API.Indicators; + +using QuantBox.CSharp2CTP; +using QuantBox.Helper.CTP; + +namespace QuantBox.OQ.Demo.Data +{ + public class DataConvert_code:Strategy + { + CThostFtdcDepthMarketDataField DepthMarketData; + + public override void OnTrade(Trade trade) + { + // 插件3.8.2.0 中开始可用,是将Trade数据中的深度数据取出 + if (DataConvert.TryConvert(trade, ref DepthMarketData)) + { + Console.WriteLine("OnTrade " + DepthMarketData.LastPrice); + Console.WriteLine("OnTrade " + DepthMarketData.UpperLimitPrice); + } + } + + public override void OnQuote(Quote quote) + { + // 插件3.8.2.1 中开始可用,是将Quote数据中的深度数据取出 + if (DataConvert.TryConvert(quote, ref DepthMarketData)) + { + Console.WriteLine("OnQuote " + DepthMarketData.LastPrice); + Console.WriteLine("OnQuote " + DepthMarketData.UpperLimitPrice); + } + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Data/DataMaker_code.cs b/Demo/QuantBox.OQ.Demo/Data/DataMaker_code.cs index a626e46..6e5ee69 100644 --- a/Demo/QuantBox.OQ.Demo/Data/DataMaker_code.cs +++ b/Demo/QuantBox.OQ.Demo/Data/DataMaker_code.cs @@ -1,101 +1,101 @@ -using System; -using System.Drawing; - -using OpenQuant.API; -using OpenQuant.API.Indicators; - -namespace QuantBox.OQ.Demo.Data -{ - /// - /// 通过策略运行的方式来生成价差序列 - /// - public class DataMaker_code : Strategy - { - static Instrument Instrument1; - static Instrument Instrument2; - Instrument Instrument3 = InstrumentManager.Instruments["IF1305 - IF1306"]; - - long barSize; - - public override void OnStrategyStart() - { - if (Instrument1 == null) - { - Instrument1 = Instrument; - } - else if (Instrument2 == null) - { - Instrument2 = Instrument; - } - - barSize = long.MaxValue; - foreach (BarRequest barRequest in DataRequests.BarRequests) - { - barSize = Math.Min(barSize, barRequest.BarSize); - } - Console.WriteLine("barSize = {0}", barSize); - } - - public override void OnStrategyStop() - { - Instrument1 = null; - Instrument2 = null; - } - - public override void OnTrade(Trade trade) - { - // 只用第二个合约的生成,数量约为第二个合约的Trade数 - // 假如第一个是IF1309,第二个是399300.SZ,这下生成的就6秒一次了 - // 按自己需求调 - if (Instrument == Instrument2) - { - if (Instrument1.Trade != null - && Instrument2.Trade != null) - { - double Price = Instrument1.Trade.Price - Instrument2.Trade.Price; - int Size = Math.Min(Instrument1.Trade.Size, Instrument2.Trade.Size); - Trade t = new Trade(Clock.Now, Price, Size); - DataManager.Add(Instrument3, t); - } - } - } - - public override void OnQuote(Quote quote) - { - // 只要有报价就会生成,数量约为两个合约Quote之和 - //if(Instrument == Instrument2) - { - if (Instrument1.Quote != null - && Instrument2.Quote != null) - { - double Ask = Instrument1.Quote.Ask - Instrument2.Quote.Bid; - int AskSize = Math.Min(Instrument1.Quote.AskSize, Instrument2.Quote.BidSize); - double Bid = Instrument1.Quote.Bid - Instrument2.Quote.Ask; - int BidSize = Math.Min(Instrument1.Quote.BidSize, Instrument2.Quote.AskSize); - Quote q = new Quote(Clock.Now, Bid, BidSize, Ask, AskSize); - DataManager.Add(Instrument3, q); - } - } - } - - public override void OnBarSlice(long size) - { - // 为了保证采样间隔一样,用户按自己的需求改 - if (size != barSize) - { - return; - } - - // 如果添加了两个合约就会触发两次,只选后面一次保存 - if (Instrument == Instrument2) - { - // 本想保存成Bar,细想没必要,保存了Trade,用户自己手工压缩成Bar就成 - double Price = Instrument1.Bar.Close - Instrument2.Bar.Close; - Trade t = new Trade(Clock.Now, Price, 0); - // 注释了。在前面的OnTrade可以生成更细致的Trade - //DataManager.Add(Instrument3,t); - } - } - } - -} +using System; +using System.Drawing; + +using OpenQuant.API; +using OpenQuant.API.Indicators; + +namespace QuantBox.OQ.Demo.Data +{ + /// + /// 通过策略运行的方式来生成价差序列 + /// + public class DataMaker_code : Strategy + { + static Instrument Instrument1; + static Instrument Instrument2; + Instrument Instrument3 = InstrumentManager.Instruments["IF1305 - IF1306"]; + + long barSize; + + public override void OnStrategyStart() + { + if (Instrument1 == null) + { + Instrument1 = Instrument; + } + else if (Instrument2 == null) + { + Instrument2 = Instrument; + } + + barSize = long.MaxValue; + foreach (BarRequest barRequest in DataRequests.BarRequests) + { + barSize = Math.Min(barSize, barRequest.BarSize); + } + Console.WriteLine("barSize = {0}", barSize); + } + + public override void OnStrategyStop() + { + Instrument1 = null; + Instrument2 = null; + } + + public override void OnTrade(Trade trade) + { + // 只用第二个合约的生成,数量约为第二个合约的Trade数 + // 假如第一个是IF1309,第二个是399300.SZ,这下生成的就6秒一次了 + // 按自己需求调 + if (Instrument == Instrument2) + { + if (Instrument1.Trade != null + && Instrument2.Trade != null) + { + double Price = Instrument1.Trade.Price - Instrument2.Trade.Price; + int Size = Math.Min(Instrument1.Trade.Size, Instrument2.Trade.Size); + Trade t = new Trade(Clock.Now, Price, Size); + DataManager.Add(Instrument3, t); + } + } + } + + public override void OnQuote(Quote quote) + { + // 只要有报价就会生成,数量约为两个合约Quote之和 + //if(Instrument == Instrument2) + { + if (Instrument1.Quote != null + && Instrument2.Quote != null) + { + double Ask = Instrument1.Quote.Ask - Instrument2.Quote.Bid; + int AskSize = Math.Min(Instrument1.Quote.AskSize, Instrument2.Quote.BidSize); + double Bid = Instrument1.Quote.Bid - Instrument2.Quote.Ask; + int BidSize = Math.Min(Instrument1.Quote.BidSize, Instrument2.Quote.AskSize); + Quote q = new Quote(Clock.Now, Bid, BidSize, Ask, AskSize); + DataManager.Add(Instrument3, q); + } + } + } + + public override void OnBarSlice(long size) + { + // 为了保证采样间隔一样,用户按自己的需求改 + if (size != barSize) + { + return; + } + + // 如果添加了两个合约就会触发两次,只选后面一次保存 + if (Instrument == Instrument2) + { + // 本想保存成Bar,细想没必要,保存了Trade,用户自己手工压缩成Bar就成 + double Price = Instrument1.Bar.Close - Instrument2.Bar.Close; + Trade t = new Trade(Clock.Now, Price, 0); + // 注释了。在前面的OnTrade可以生成更细致的Trade + //DataManager.Add(Instrument3,t); + } + } + } + +} diff --git a/Demo/QuantBox.OQ.Demo/Data/DynamicBar_code.cs b/Demo/QuantBox.OQ.Demo/Data/DynamicBar_code.cs index f74eb04..c6b90c6 100644 --- a/Demo/QuantBox.OQ.Demo/Data/DynamicBar_code.cs +++ b/Demo/QuantBox.OQ.Demo/Data/DynamicBar_code.cs @@ -1,60 +1,60 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -namespace QuantBox.OQ.Demo.Data -{ - /// - /// 实时更新的Bar - /// - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=118 - /// - /// 注:貌似在OnQuote中直接引用Bar.High,Bar.Low,他会根据新的数据进行更新。 - /// - public class DynamicBar_code:Strategy - { - double dbOpen = double.NaN; - double dbHigh = double.MinValue; - double dbLow = double.MaxValue; - double dbClose = double.NaN; - double dbVolume = 0; - - public override void OnTrade(Trade trade) - { - //每次在行情到来时更新最高、最低和成交量 - dbHigh = Math.Max(trade.Price, dbHigh); - dbLow = Math.Min(trade.Price, dbLow); - dbClose = trade.Price; - dbVolume += trade.Size; - - //其他代码 - } - - public override void OnBarOpen(Bar bar) - { - //因为先OnTrade来后才OnBarOpen, - //如果只在OnBarOpen中更新高低与量, - //这时在OnTrade中计算的高低与量并不准确, - //所以要提前到前一个Bar在OnBar时更新数据 - dbOpen = bar.Close; - } - - public override void OnBar(Bar bar) - { - // 其他代码,用完后再重置 - - // 重置 - if (180 == bar.Size) - { - dbHigh = double.MinValue; - dbLow = double.MaxValue; - dbVolume = 0; - } - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +namespace QuantBox.OQ.Demo.Data +{ + /// + /// 实时更新的Bar + /// + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=118 + /// + /// 注:貌似在OnQuote中直接引用Bar.High,Bar.Low,他会根据新的数据进行更新。 + /// + public class DynamicBar_code:Strategy + { + double dbOpen = double.NaN; + double dbHigh = double.MinValue; + double dbLow = double.MaxValue; + double dbClose = double.NaN; + double dbVolume = 0; + + public override void OnTrade(Trade trade) + { + //每次在行情到来时更新最高、最低和成交量 + dbHigh = Math.Max(trade.Price, dbHigh); + dbLow = Math.Min(trade.Price, dbLow); + dbClose = trade.Price; + dbVolume += trade.Size; + + //其他代码 + } + + public override void OnBarOpen(Bar bar) + { + //因为先OnTrade来后才OnBarOpen, + //如果只在OnBarOpen中更新高低与量, + //这时在OnTrade中计算的高低与量并不准确, + //所以要提前到前一个Bar在OnBar时更新数据 + dbOpen = bar.Close; + } + + public override void OnBar(Bar bar) + { + // 其他代码,用完后再重置 + + // 重置 + if (180 == bar.Size) + { + dbHigh = double.MinValue; + dbLow = double.MaxValue; + dbVolume = 0; + } + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Data/MyExtFilter_Scenario.cs b/Demo/QuantBox.OQ.Demo/Data/MyExtFilter_Scenario.cs index 29142aa..fbfa667 100644 --- a/Demo/QuantBox.OQ.Demo/Data/MyExtFilter_Scenario.cs +++ b/Demo/QuantBox.OQ.Demo/Data/MyExtFilter_Scenario.cs @@ -1,75 +1,75 @@ -using System; -using System.Collections.Generic; - -using OpenQuant.API; -using OpenQuant.API.Engine; - -using QuantBox.OQ.Extensions; - -namespace QuantBox.OQ.Demo.Data -{ - public class MyExtFilter_Scenario : Scenario - { - class MyExtFilter : ExtMarketDataFilter - { - Dictionary _trades = new Dictionary(); - - MarketDataFilter filter; - - // 构造函数不能省 - public MyExtFilter(MarketDataProvider provider, MarketDataFilter filter) - : base(provider) - { - this.filter = filter; - } - - public override OpenQuant.API.Trade FilterTrade(OpenQuant.API.Trade trade, string symbol) - { - _trades[symbol] = trade; - - // 在这之前可以做自己的过滤 - Trade t = trade; - if (filter != null) - { - t = filter.FilterTrade(trade, symbol); - } - if (t != null) - { - EmitTrade(symbol, Clock.Now, t.Price, t.Size); - } - else - { - return null; - } - - Trade t1, t2; - - if ("IF1306-IF1307".Contains(symbol) - || "IF1306-IF1307*2".Contains(symbol)) - { - if (_trades.TryGetValue("IF1306", out t1) - && _trades.TryGetValue("IF1307", out t2)) - { - EmitTrade("IF1306-IF1307", Clock.Now, t1.Price - t2.Price, 0); - EmitTrade("IF1306-IF1307*2", Clock.Now, t1.Price - t2.Price * 2.0, 0); - } - } - - - // 注意,这个地方一定要返回null - // 这实际上是让插件内部的Emit不调用 - return null; - } - } - - - public override void Run() - { - MarketDataProvider.Filter = new MyExtFilter(MarketDataProvider,new MyFilter()); - - Start(); - } - } - - -} +using System; +using System.Collections.Generic; + +using OpenQuant.API; +using OpenQuant.API.Engine; + +using QuantBox.OQ.Extensions; + +namespace QuantBox.OQ.Demo.Data +{ + public class MyExtFilter_Scenario : Scenario + { + class MyExtFilter : ExtMarketDataFilter + { + Dictionary _trades = new Dictionary(); + + MarketDataFilter filter; + + // 构造函数不能省 + public MyExtFilter(MarketDataProvider provider, MarketDataFilter filter) + : base(provider) + { + this.filter = filter; + } + + public override OpenQuant.API.Trade FilterTrade(OpenQuant.API.Trade trade, string symbol) + { + _trades[symbol] = trade; + + // 在这之前可以做自己的过滤 + Trade t = trade; + if (filter != null) + { + t = filter.FilterTrade(trade, symbol); + } + if (t != null) + { + EmitTrade(symbol, Clock.Now, t.Price, t.Size); + } + else + { + return null; + } + + Trade t1, t2; + + if ("IF1306-IF1307".Contains(symbol) + || "IF1306-IF1307*2".Contains(symbol)) + { + if (_trades.TryGetValue("IF1306", out t1) + && _trades.TryGetValue("IF1307", out t2)) + { + EmitTrade("IF1306-IF1307", Clock.Now, t1.Price - t2.Price, 0); + EmitTrade("IF1306-IF1307*2", Clock.Now, t1.Price - t2.Price * 2.0, 0); + } + } + + + // 注意,这个地方一定要返回null + // 这实际上是让插件内部的Emit不调用 + return null; + } + } + + + public override void Run() + { + MarketDataProvider.Filter = new MyExtFilter(MarketDataProvider,new MyFilter()); + + Start(); + } + } + + +} diff --git a/Demo/QuantBox.OQ.Demo/Data/MyFilter.cs b/Demo/QuantBox.OQ.Demo/Data/MyFilter.cs index 93d1001..7be5f6c 100644 --- a/Demo/QuantBox.OQ.Demo/Data/MyFilter.cs +++ b/Demo/QuantBox.OQ.Demo/Data/MyFilter.cs @@ -1,124 +1,124 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Engine; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; -using System.Collections.Generic; -using QuantBox.OQ.Demo.Helper; - -namespace QuantBox.OQ.Demo.Data -{ - public class MyFilter : MarketDataFilter - { - Dictionary goodTrades = new Dictionary(); - Dictionary TimeHelpers = new Dictionary(); - - bool isRightTime(string symbol, DateTime datetime) - { - int nDatetime = datetime.Hour * 100 + datetime.Minute; - - TimeHelper th; - if(!TimeHelpers.TryGetValue(symbol,out th)) - { - th = new TimeHelper(symbol); - TimeHelpers[symbol] = th; - } - - return th.IsTradingTime(datetime); - } - - public override Bar FilterBarOpen(Bar bar, string symbol) - { - // 只过滤Time Bar - if (bar.Type != BarType.Time) - return bar; - - // 日线数据不过滤 - if (bar.Size >= 86400) - return bar; - - if (isRightTime(symbol, bar.DateTime)) - return bar; - - return null; - } - - public override Bar FilterBar(Bar bar, string symbol) - { - if (bar.Type != BarType.Time) - return bar; - - if (bar.Size >= 86400) - return bar; - - // 注意!!!!! - // 商品是13点30中中午开始,而如果你设置的是1小时一个Bar - // 只使用DateTime进行判断会导致1点到2点的Bar被丢弃 - // 所以要多判断些条件 - if (isRightTime(symbol, bar.DateTime) - || isRightTime(symbol, bar.EndTime) - || isRightTime(symbol, bar.BeginTime)) - return bar; - - return null; - } - - public override Trade FilterTrade(Trade trade, string symbol) - { - // 进行Trade过滤下面只给一个示例 - return trade; - - Trade lastGoodTrade = null; - - //检查数据表中是否有正常交易 - if (goodTrades.TryGetValue(symbol, out lastGoodTrade)) - { - // 检查是否有数据特征 - - //检查新的交易与上一个正常交易相比,价差是否在0.5%以上 - if (Math.Abs((1 - lastGoodTrade.Price / trade.Price) * 100) < 0.5) - { - //是正常交易,就更新为上一个正常交易 - goodTrades[symbol] = trade; - return trade; - } - else - { - return null; - } - } - else - { - // 将第一次交易数据作为初始正常数据 - goodTrades[symbol] = trade; - // 将此数据添加到数据表里(第一个数据) - return trade; - } - } - - public override Quote FilterQuote(OpenQuant.API.Quote quote, string symbol) - { - // 接收所有报价 - return quote; - } - } -} - -/* -注意:只能对一个Provider设置一个Filter,重复设置会覆盖 - -1.在Scenario中使用 -MarketDataProvider.Filter = new MyFilter(); - -2.在Script中使用 -MarketDataProvider provider = (MarketDataProvider)ProviderManager.Providers["CTP"]; -provider.Filter = new MyFilter(); - -3.在Strategy中使用 -MarketDataProvider.Filter = new MyFilter(); - - */ +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Engine; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; +using System.Collections.Generic; +using QuantBox.OQ.Demo.Helper; + +namespace QuantBox.OQ.Demo.Data +{ + public class MyFilter : MarketDataFilter + { + Dictionary goodTrades = new Dictionary(); + Dictionary TimeHelpers = new Dictionary(); + + bool isRightTime(string symbol, DateTime datetime) + { + int nDatetime = datetime.Hour * 100 + datetime.Minute; + + TimeHelper th; + if(!TimeHelpers.TryGetValue(symbol,out th)) + { + th = new TimeHelper(symbol); + TimeHelpers[symbol] = th; + } + + return th.IsTradingTime(datetime); + } + + public override Bar FilterBarOpen(Bar bar, string symbol) + { + // 只过滤Time Bar + if (bar.Type != BarType.Time) + return bar; + + // 日线数据不过滤 + if (bar.Size >= 86400) + return bar; + + if (isRightTime(symbol, bar.DateTime)) + return bar; + + return null; + } + + public override Bar FilterBar(Bar bar, string symbol) + { + if (bar.Type != BarType.Time) + return bar; + + if (bar.Size >= 86400) + return bar; + + // 注意!!!!! + // 商品是13点30中中午开始,而如果你设置的是1小时一个Bar + // 只使用DateTime进行判断会导致1点到2点的Bar被丢弃 + // 所以要多判断些条件 + if (isRightTime(symbol, bar.DateTime) + || isRightTime(symbol, bar.EndTime) + || isRightTime(symbol, bar.BeginTime)) + return bar; + + return null; + } + + public override Trade FilterTrade(Trade trade, string symbol) + { + // 进行Trade过滤下面只给一个示例 + return trade; + + Trade lastGoodTrade = null; + + //检查数据表中是否有正常交易 + if (goodTrades.TryGetValue(symbol, out lastGoodTrade)) + { + // 检查是否有数据特征 + + //检查新的交易与上一个正常交易相比,价差是否在0.5%以上 + if (Math.Abs((1 - lastGoodTrade.Price / trade.Price) * 100) < 0.5) + { + //是正常交易,就更新为上一个正常交易 + goodTrades[symbol] = trade; + return trade; + } + else + { + return null; + } + } + else + { + // 将第一次交易数据作为初始正常数据 + goodTrades[symbol] = trade; + // 将此数据添加到数据表里(第一个数据) + return trade; + } + } + + public override Quote FilterQuote(OpenQuant.API.Quote quote, string symbol) + { + // 接收所有报价 + return quote; + } + } +} + +/* +注意:只能对一个Provider设置一个Filter,重复设置会覆盖 + +1.在Scenario中使用 +MarketDataProvider.Filter = new MyFilter(); + +2.在Script中使用 +MarketDataProvider provider = (MarketDataProvider)ProviderManager.Providers["CTP"]; +provider.Filter = new MyFilter(); + +3.在Strategy中使用 +MarketDataProvider.Filter = new MyFilter(); + + */ diff --git a/Demo/QuantBox.OQ.Demo/Data/Non-natural_TimeBar_code.cs b/Demo/QuantBox.OQ.Demo/Data/Non-natural_TimeBar_code.cs index 680443c..fb4753a 100644 --- a/Demo/QuantBox.OQ.Demo/Data/Non-natural_TimeBar_code.cs +++ b/Demo/QuantBox.OQ.Demo/Data/Non-natural_TimeBar_code.cs @@ -1,68 +1,68 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -namespace QuantBox.OQ.Demo.Data -{ - /// - /// 使用非自然时间的Bar - /// 要 - /// - /// 解决方案来源于英文官网 - /// http://www.smartquant.com/forums/viewtopic.php?f=64&t=7776 - /// - public class Non_natural_TimeBar_code : Strategy - { - //临时Bar序列 - private BarSeries bars = null; - private BarSeries bars30min = new BarSeries(); - - /* - 按照股指的时间要求,时间划分是这样的 - 9:15 - 9:45 - 10:15 - 10:45 - 11:15-11:30 13:00-13:15 两个15分钟被午休隔开了 - 13:45 - 14:15 - 14:45 - 15:15 交割日时只到15:00,已经到最后一天了,少15分钟也没什么 - */ - public override void OnBar(Bar bar) - { - //只处理15分钟的 - if (900 == bar.Size) - { - if (bars == null) - bars = new BarSeries(); - - bars.Add(bar); - - //在处理11:15-11:30 13:00-13:15这两个15分钟时会合并成一个 - if (bars.Count == 2) // 2 * 15min = 30 min - { - // get OHLC values for 30min bar - double open = bars[0].Open; - double high = bars.HighestHigh(); - double low = bars.LowestLow(); - double close = bars[1].Close; - long volume = bars[0].Volume + bars[1].Volume; - - // todo something - Bar b = new Bar(bars[0].DateTime, open, high, low, close, volume, 900 * 2); - bars30min.Add(b); - Console.WriteLine(b); - - // reset 15min bar series - bars = null; - } - } - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +namespace QuantBox.OQ.Demo.Data +{ + /// + /// 使用非自然时间的Bar + /// 要 + /// + /// 解决方案来源于英文官网 + /// http://www.smartquant.com/forums/viewtopic.php?f=64&t=7776 + /// + public class Non_natural_TimeBar_code : Strategy + { + //临时Bar序列 + private BarSeries bars = null; + private BarSeries bars30min = new BarSeries(); + + /* + 按照股指的时间要求,时间划分是这样的 + 9:15 + 9:45 + 10:15 + 10:45 + 11:15-11:30 13:00-13:15 两个15分钟被午休隔开了 + 13:45 + 14:15 + 14:45 + 15:15 交割日时只到15:00,已经到最后一天了,少15分钟也没什么 + */ + public override void OnBar(Bar bar) + { + //只处理15分钟的 + if (900 == bar.Size) + { + if (bars == null) + bars = new BarSeries(); + + bars.Add(bar); + + //在处理11:15-11:30 13:00-13:15这两个15分钟时会合并成一个 + if (bars.Count == 2) // 2 * 15min = 30 min + { + // get OHLC values for 30min bar + double open = bars[0].Open; + double high = bars.HighestHigh(); + double low = bars.LowestLow(); + double close = bars[1].Close; + long volume = bars[0].Volume + bars[1].Volume; + + // todo something + Bar b = new Bar(bars[0].DateTime, open, high, low, close, volume, 900 * 2); + bars30min.Add(b); + Console.WriteLine(b); + + // reset 15min bar series + bars = null; + } + } + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Data/SaveData_code.cs b/Demo/QuantBox.OQ.Demo/Data/SaveData_code.cs index 4daff57..c0b4fe3 100644 --- a/Demo/QuantBox.OQ.Demo/Data/SaveData_code.cs +++ b/Demo/QuantBox.OQ.Demo/Data/SaveData_code.cs @@ -1,29 +1,29 @@ -using System; -using System.Drawing; - -using OpenQuant.API; -using OpenQuant.API.Indicators; - -namespace QuantBox.OQ.Demo.Data -{ - /// - /// 使用策略来保存行情 - /// - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=24 - /// - public class SaveData_code:Strategy - { - public override void OnTrade(Trade trade) - { - // 模拟行情时,不保存 - if (StrategyMode.Simulation != Mode) - DataManager.Add(Instrument, trade); - } - - public override void OnQuote(Quote quote) - { - if (StrategyMode.Simulation != Mode) - DataManager.Add(Instrument, quote); - } - } -} +using System; +using System.Drawing; + +using OpenQuant.API; +using OpenQuant.API.Indicators; + +namespace QuantBox.OQ.Demo.Data +{ + /// + /// 使用策略来保存行情 + /// + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=24 + /// + public class SaveData_code:Strategy + { + public override void OnTrade(Trade trade) + { + // 模拟行情时,不保存 + if (StrategyMode.Simulation != Mode) + DataManager.Add(Instrument, trade); + } + + public override void OnQuote(Quote quote) + { + if (StrategyMode.Simulation != Mode) + DataManager.Add(Instrument, quote); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Helper/CloseTodayHelper.cs b/Demo/QuantBox.OQ.Demo/Helper/CloseTodayHelper.cs index a8d5eda..7b901bf 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/CloseTodayHelper.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/CloseTodayHelper.cs @@ -6,10 +6,19 @@ namespace QuantBox.OQ.Demo.Helper { + /// + /// 平今仓助手,上交所有平令仓和平昨仓区别 + /// public class CloseTodayHelper { + /// + /// 是否上交所 + /// public bool IsSHFE { get; private set; } - + /// + /// 是否平今仓 + /// + /// public CloseTodayHelper(EnumExchangeID exchange) { this.IsSHFE = (exchange == EnumExchangeID.SHFE); @@ -19,7 +28,11 @@ public CloseTodayHelper(bool IsSHFE) { this.IsSHFE = IsSHFE; } - + /// + /// 平今仓转换成平昨仓标志 + /// + /// + /// public EnumOpenClose Transform(EnumOpenClose OpenClose) { if (!IsSHFE) @@ -29,22 +42,27 @@ public EnumOpenClose Transform(EnumOpenClose OpenClose) } return OpenClose; } - + /// + /// 计算平昨仓和平 + /// + /// + /// + /// public double GetCloseAndQty(PositionRecord pos,out EnumOpenClose OpenClose) { - double qty = 0; - OpenClose = EnumOpenClose.CLOSE; - if (IsSHFE) + double qty = 0;//可平仓量 + OpenClose = EnumOpenClose.CLOSE;//开平标志,默认设置为平昨仓 + if (IsSHFE)//是否上交所 { - // 上海,先检查今仓 + // 上海,先检查今仓可平量,今仓可平量=实际今仓量-挂平今量 qty = pos.QtyToday - pos.FrozenCloseToday; - if (qty > 0) + if (qty > 0)//今仓可平量>0时 { - OpenClose = EnumOpenClose.CLOSE_TODAY; + OpenClose = EnumOpenClose.CLOSE_TODAY;//设置平今标志 } - else + else//今仓可平量==0时 { - // 先算出昨仓,再查挂的昨平仓有多少 + // 计算出昨可平仓量,再查挂的昨平仓有多少,昨仓=(实际持仓-实际今仓)-(挂平仓量 - 挂平今量) qty = (pos.Qty - pos.QtyToday) - (pos.FrozenClose - pos.FrozenCloseToday); } } diff --git a/Demo/QuantBox.OQ.Demo/Helper/CloseTodayHelper.cs.orig b/Demo/QuantBox.OQ.Demo/Helper/CloseTodayHelper.cs.orig new file mode 100644 index 0000000..7b901bf --- /dev/null +++ b/Demo/QuantBox.OQ.Demo/Helper/CloseTodayHelper.cs.orig @@ -0,0 +1,77 @@ +using QuantBox.OQ.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace QuantBox.OQ.Demo.Helper +{ + /// + /// 平今仓助手,上交所有平令仓和平昨仓区别 + /// + public class CloseTodayHelper + { + /// + /// 是否上交所 + /// + public bool IsSHFE { get; private set; } + /// + /// 是否平今仓 + /// + /// + public CloseTodayHelper(EnumExchangeID exchange) + { + this.IsSHFE = (exchange == EnumExchangeID.SHFE); + } + + public CloseTodayHelper(bool IsSHFE) + { + this.IsSHFE = IsSHFE; + } + /// + /// 平今仓转换成平昨仓标志 + /// + /// + /// + public EnumOpenClose Transform(EnumOpenClose OpenClose) + { + if (!IsSHFE) + { + if (OpenClose == EnumOpenClose.CLOSE_TODAY) + return EnumOpenClose.CLOSE; + } + return OpenClose; + } + /// + /// 计算平昨仓和平 + /// + /// + /// + /// + public double GetCloseAndQty(PositionRecord pos,out EnumOpenClose OpenClose) + { + double qty = 0;//可平仓量 + OpenClose = EnumOpenClose.CLOSE;//开平标志,默认设置为平昨仓 + if (IsSHFE)//是否上交所 + { + // 上海,先检查今仓可平量,今仓可平量=实际今仓量-挂平今量 + qty = pos.QtyToday - pos.FrozenCloseToday; + if (qty > 0)//今仓可平量>0时 + { + OpenClose = EnumOpenClose.CLOSE_TODAY;//设置平今标志 + } + else//今仓可平量==0时 + { + // 计算出昨可平仓量,再查挂的昨平仓有多少,昨仓=(实际持仓-实际今仓)-(挂平仓量 - 挂平今量) + qty = (pos.Qty - pos.QtyToday) - (pos.FrozenClose - pos.FrozenCloseToday); + } + } + else + { + // 非上海,直接返回 + qty = pos.Qty - pos.FrozenClose; + } + return qty; + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Helper/DualPosition.cs b/Demo/QuantBox.OQ.Demo/Helper/DualPosition.cs index d133320..2ddad42 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/DualPosition.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/DualPosition.cs @@ -18,14 +18,24 @@ namespace QuantBox.OQ.Demo.Helper /// public class DualPosition { - + /// + /// //平今仓助手 + /// public CloseTodayHelper CloseTodayHelper; + /// + /// //多头仓位记录 + /// public PositionRecord Long = new PositionRecord(); + /// + /// //空头仓位记录 + /// public PositionRecord Short = new PositionRecord(); public OrderBook_OneSide_Order Buy = new OrderBook_OneSide_Order(OrderSide.Buy); public OrderBook_OneSide_Order Sell = new OrderBook_OneSide_Order(OrderSide.Sell); - + /// + /// 订单的开平仓字典 + /// public Dictionary Order_OpenClose = new Dictionary(); public DualPosition(string symbol) @@ -34,27 +44,37 @@ public DualPosition(string symbol) } public string Symbol { get; private set; } - + /// + /// 多头持仓量 + /// public double LongQty { get { return Long.Qty; } } - + /// + /// 空头持仓量 + /// public double ShortQty { get { return Short.Qty; } } - + /// + /// 得到买入数量 + /// public double BidQty { get { return Buy.Size(); } } - + /// + /// 得到卖出数量 + /// public double AskQty { get { return Sell.Size(); } } - + /// + /// 得到买入价位文本信息 + /// public string BidString { get @@ -65,7 +85,9 @@ public string BidString Buy.PriceByIndex(0)); } } - + /// + /// 得到卖出价位文本信息 + /// public string AskString { get @@ -89,16 +111,20 @@ public void ChangeTradingDay() Buy.Clear(); Sell.Clear(); - Long.ChangeTradingDay(); - Short.ChangeTradingDay(); + Long.ChangeTradingDay();//多头换日 + Short.ChangeTradingDay();//空头换日 } } - + /// + /// 实际持仓 + /// public double NetQty { - get { return Long.Qty - Short.Qty; } + get { return Long.Qty - Short.Qty; }//多头仓 - 空头仓 } - + /// + /// 是否等待 + /// public bool IsPending { get { return Buy.IsPending || Sell.IsPending; } @@ -185,9 +211,9 @@ public void Filled(Order order) { lock (this) { - double LastQty = order.LastQty; - double LastPrice = order.LastPrice; - bool IsDone = order.IsDone; + double LastQty = order.LastQty;//得到最后的填充(部分填充)此订单的数量 + double LastPrice = order.LastPrice;//得到最后的填充(部分填充)此订单价格 + bool IsDone = order.IsDone;//返回true,如果这个订单最终状态(填充,拒绝或取消) EnumOpenClose OpenClose = GetOpenClose(order); @@ -322,22 +348,32 @@ public EnumOpenClose OrderCancelled(Order order) return OpenClose; } } - + /// + /// 得到订单的开平标志 + /// + /// 订单 + /// 返回值:开平仓标记 public EnumOpenClose GetOpenClose(Order order) { - EnumOpenClose OpenClose = EnumOpenClose.OPEN; + EnumOpenClose OpenClose = EnumOpenClose.OPEN;//开平仓标记 + //得到指定order订单的开平仓标记,TryGetValue函数找到时则返回TURE,并返回指定的OpenClose开平仓标记 if(Order_OpenClose.TryGetValue(order, out OpenClose)) return OpenClose; + //没有找到则返回OPEN标记 return EnumOpenClose.OPEN; } - + /// + /// 订单被拒绝 + /// + /// + /// public EnumOpenClose OrderRejected(Order order) { lock (this) { - double LeavesQty = order.LeavesQty; + double LeavesQty = order.LeavesQty;//得到剩余的订单数量 - EnumOpenClose OpenClose = GetOpenClose(order); + EnumOpenClose OpenClose = GetOpenClose(order);//开平标记 switch (OpenClose) { diff --git a/Demo/QuantBox.OQ.Demo/Helper/GetBrokerInfoHelper.cs b/Demo/QuantBox.OQ.Demo/Helper/GetBrokerInfoHelper.cs index 531cb39..5bfda93 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/GetBrokerInfoHelper.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/GetBrokerInfoHelper.cs @@ -6,14 +6,21 @@ namespace QuantBox.OQ.Demo.Helper { + /// + /// 获取代理商信息助手 + /// public class GetBrokerInfoHelper { - private const string PosiDirection = "PosiDirection"; - private const string Long = "Long"; - private const string PositionDate = "PositionDate"; - private const string Today = "Today"; - private const string Position = "Position"; - + private const string PosiDirection = "PosiDirection";//仓位方向 + private const string Long = "Long";// + private const string PositionDate = "PositionDate";//仓位日期 + private const string Today = "Today";//今仓 + private const string Position = "Position";//仓位 + /// + /// 转换 + /// + /// + /// public static void Transform(BrokerAccount brokerAccount,DualPosition dualPosition) { if (brokerAccount == null||dualPosition == null) diff --git a/Demo/QuantBox.OQ.Demo/Helper/OpenCloseHelper.cs b/Demo/QuantBox.OQ.Demo/Helper/OpenCloseHelper.cs index f8635df..d3a0615 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/OpenCloseHelper.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/OpenCloseHelper.cs @@ -5,6 +5,9 @@ namespace QuantBox.OQ.Demo.Helper { + /// + /// 开平仓助手 + /// public class OpenCloseHelper { public static EnumOpenClose CheckOpenClose(Order order) diff --git a/Demo/QuantBox.OQ.Demo/Helper/OrderBook_BothSide_Size.cs b/Demo/QuantBox.OQ.Demo/Helper/OrderBook_BothSide_Size.cs index b7bf624..bf16b56 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/OrderBook_BothSide_Size.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/OrderBook_BothSide_Size.cs @@ -6,6 +6,9 @@ namespace QuantBox.OQ.Demo.Helper { + /// + /// 双向挂单管理 + /// public class OrderBook_BothSide_Size { public OrderBook_OneSide_Size Sell = new OrderBook_OneSide_Size(OrderSide.Sell); diff --git a/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Order.cs b/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Order.cs index 7f2fece..2fb267b 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Order.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Order.cs @@ -6,11 +6,26 @@ namespace QuantBox.OQ.Demo.Helper { + /// + /// 挂单方向及动作 + /// public class OrderBook_OneSide_Order : IComparer, IComparer { + /// + /// //订单方向(buy or sell) + /// public OrderSide Side; + /// + /// 订单的排序列表的集合 + /// private SortedList> _Grid; + /// + /// //价格助手 + /// public PriceHelper PriceHelper; + /// + /// //撤单的散列集合 + /// private HashSet cancelList = new HashSet(); public IEnumerable>> GridList @@ -34,12 +49,19 @@ public int Compare(int x, int y) { return x.CompareTo(y) * (Side == OrderSide.Buy ? -1 : 1); } - + /// + /// 比较两个订单的时间先后顺序 + /// + /// + /// + /// public int Compare(Order x, Order y) { return x.DateTime.CompareTo(y.DateTime); } - + /// + /// 订单数>0时,需要等待 + /// public bool IsPending { get { return _Grid.Count > 0; } @@ -78,7 +100,10 @@ public void Add(Order order) set.Add(order); } } - + /// + /// 删除订单 + /// + /// public void Remove(Order order) { lock (this) @@ -98,7 +123,11 @@ public void Remove(Order order) } } } - + /// + /// 到剩余的订单数量之和 + /// + /// + /// public double Size(SortedSet set) { //lock (this) @@ -106,12 +135,15 @@ public double Size(SortedSet set) double sum = 0; foreach (var o in set) { - sum += o.LeavesQty; + sum += o.LeavesQty;//得到剩余的订单数量之和 } return sum; } } - + /// + /// 获取所有订单的 + /// + /// public double Size() { //lock (this) @@ -136,7 +168,11 @@ public double SizeByIndex(int index) return Size(set); } } - + /// + /// + /// + /// + /// public double SizeByLevel(int level) { //lock (this) @@ -149,7 +185,11 @@ public double SizeByLevel(int level) return Size(set); } } - + /// + /// 获取价格水平,取TickSize整数倍 + /// + /// + /// public double SizeByPrice(double price) { lock (this) @@ -158,7 +198,10 @@ public double SizeByPrice(double price) return SizeByLevel(key); } } - + /// + /// 撤单 + /// + /// public int Cancel() { lock (this) @@ -171,25 +214,33 @@ public int Cancel() return cnt; } } - + /// + /// 撤消挂单 + /// + /// 订单集合 + /// 返回撤单数量 public int Cancel(SortedSet set) { lock (this) { - int cnt = 0; - foreach (var o in set.ToList()) + int cnt = 0;//撤单数量 + foreach (var o in set.ToList())// 0 为推断类型变量,他的类型取决存储在set中的类型 { - if (!o.IsDone) + if (!o.IsDone)//返回true,如果这个订单最终状态(填充,拒绝或取消) { - cancelList.Add(o); - o.Cancel(); + cancelList.Add(o);//撤单列表添加 + o.Cancel();//取消此订单 ++cnt; } } return cnt; } } - + /// + /// 撤消对应挂单 + /// + /// + /// public int CancelByIndex(int index) { lock (this) @@ -227,7 +278,11 @@ public int CancelByIndex(int index) // return cnt; // } //} - + /// + /// 取消与price不同的 + /// + /// + /// public int CancelNotEqualPrice(double price) { lock (this) @@ -261,7 +316,11 @@ public int CancelNotEqualPrice(double price) // return cnt; // } //} - + /// + /// 价格索引 + /// + /// + /// public double PriceByIndex(int index) { //lock (this) @@ -273,19 +332,22 @@ public double PriceByIndex(int index) return PriceHelper.GetPriceByLevel(key); } } - + /// + /// 显示对应订单价格、剩余订单数量和 + /// + /// public override string ToString() { string str = ""; foreach (var i in _Grid) { - double price = PriceHelper.GetPriceByLevel(i.Key); - double sum = 0; + double price = PriceHelper.GetPriceByLevel(i.Key);//获得订单价格 + double sum = 0;//剩余的订单总数量 foreach (var o in i.Value) { - sum += o.LeavesQty; + sum += o.LeavesQty;//LeavesQty得到剩余的订单数量 } - str += string.Format("{0} {1}{2}", price, sum, Environment.NewLine); + str += string.Format("{0} {1}{2}", price, sum, Environment.NewLine);//Environment.NewLine转换字符串 } return str; } diff --git a/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Size.cs b/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Size.cs index f39494a..f15f588 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Size.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/OrderBook_OneSide_Size.cs @@ -6,6 +6,9 @@ namespace QuantBox.OQ.Demo.Helper { + /// + /// 单向挂单管理 + /// public class OrderBook_OneSide_Size : IComparer { public OrderSide Side; diff --git a/Demo/QuantBox.OQ.Demo/Helper/PositionRecord.cs b/Demo/QuantBox.OQ.Demo/Helper/PositionRecord.cs index e8330d0..b5ceadd 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/PositionRecord.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/PositionRecord.cs @@ -1,161 +1,200 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace QuantBox.OQ.Demo.Helper -{ - /// - /// 持仓量信息如何保存? - /// 1.总持仓和今仓。使用此方式,这样在下单时对非上海的可以直接判断 - /// 2.昨持仓和今仓 - /// - /// 1.上海与非上海都用一样的保存方法。使用此方式,统一 - /// 2.只上海分昨和今 - /// - public class PositionRecord - { - /// - /// 实际持仓 - /// - public double Qty { get; set; } - /// - /// 实际持今仓量 - /// - public double QtyToday { get; set; } - /// - /// 挂开仓量 - /// - public double FrozenOpen { get; private set; } - /// - /// 挂平仓量 - /// - public double FrozenClose { get; private set; } - /// - /// 挂平今量 - /// - public double FrozenCloseToday { get; private set; } - /// - /// 开仓手数累计 - /// - public double CumOpenQty { get; private set; } - /// - /// 撤单次数累计,注意,不区分主动撤单与被动撤单 - /// - public double CumCancelCnt { get; set; } - /// - /// 持仓成本 - /// - public double HoldingCost { get; private set; } - - - public void Reset() - { - Qty = 0; - HoldingCost = 0; - - ChangeTradingDay(); - } - - public void ChangeTradingDay() - { - QtyToday = 0; - FrozenOpen = 0; - FrozenClose = 0; - FrozenCloseToday = 0; - CumOpenQty = 0; - CumCancelCnt = 0; - } - - /// - /// 持仓平均成本 - /// - public double AvgPrice - { - get - { - if (Qty == 0) - return 0; - else - return HoldingCost / Qty; - } - } - - public override string ToString() - { - return string.Format("持仓量:{0},挂开仓量:{1},挂平仓量:{2},开仓手数累计:{3}", - Qty, FrozenOpen, FrozenClose, CumOpenQty); - } - - public void NewOrderOpen(double Qty) - { - FrozenClose += Qty; - } - - public void NewOrderClose(double Qty) - { - FrozenClose += Qty; - } - - public void NewOrderCloseToday(double Qty) - { - FrozenCloseToday += Qty; - FrozenClose += Qty; - } - - public void FilledOpen(double LastQty, double LastPrice) - { - Qty += LastQty; - QtyToday += LastQty; - FrozenOpen -= LastQty; - CumOpenQty += LastQty; - HoldingCost += LastPrice * LastQty; - } - - public void FilledClose(double LastQty, double LastPrice) - { - Qty -= LastQty; - FrozenClose -= LastQty; - if (Qty == 0) - { - HoldingCost = 0; - } - else - { - HoldingCost -= LastPrice * LastQty; - } - } - - public void FilledCloseToday(double LastQty, double LastPrice) - { - Qty -= LastQty; - QtyToday -= LastQty; - FrozenClose -= LastQty; - FrozenCloseToday -= LastQty; - if (Qty == 0) - { - HoldingCost = 0; - } - else - { - HoldingCost -= LastPrice * LastQty; - } - } - - public void OrderRejectedOpen(double LeavesQty) - { - FrozenOpen -= LeavesQty; - } - - public void OrderRejectedClose(double LeavesQty) - { - FrozenClose -= LeavesQty; - } - - public void OrderRejectedCloseToday(double LeavesQty) - { - FrozenCloseToday -= LeavesQty; - FrozenClose -= LeavesQty; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace QuantBox.OQ.Demo.Helper +{ + /// + /// 持仓量信息如何保存? + /// 1.总持仓和今仓。使用此方式,这样在下单时对非上海的可以直接判断 + /// 2.昨持仓和今仓 + /// + /// 1.上海与非上海都用一样的保存方法。使用此方式,统一 + /// 2.只上海分昨和今 + /// + public class PositionRecord + { + /// + /// 实际持仓 + /// + public double Qty { get; set; } + /// + /// 实际持今仓量 + /// + public double QtyToday { get; set; } + /// + /// 挂开仓量 + /// + public double FrozenOpen { get; private set; } + /// + /// 挂平仓量 + /// + public double FrozenClose { get; private set; } + /// + /// 挂平今量 + /// + public double FrozenCloseToday { get; private set; } + /// + /// 开仓手数累计 + /// + public double CumOpenQty { get; private set; } + /// + /// 撤单次数累计,注意,不区分主动撤单与被动撤单 + /// + public double CumCancelCnt { get; set; } + /// + /// 持仓成本 + /// + public double HoldingCost { get; private set; } + + /// + /// 重新初始化 + /// + public void Reset() + { + Qty = 0;//实际持仓量 + HoldingCost = 0;//持仓成本 + + ChangeTradingDay(); + } + + /// + /// 换日,用户自己要记得挂单要撤 + /// + public void ChangeTradingDay() + { + QtyToday = 0;//今实际持仓量=0 + FrozenOpen = 0;//挂开仓量=0 + FrozenClose = 0;//挂平仓量=0 + FrozenCloseToday = 0;//挂平今量=0 + CumOpenQty = 0;//开仓手数累计=0 + CumCancelCnt = 0;//撤单次数累计=0 + } + + /// + /// 持仓平均成本 + /// + public double AvgPrice + { + get + { + if (Qty == 0) + return 0; + else + return HoldingCost / Qty;//持仓成本/持仓量 + } + } + /// + /// 转换持仓量信息为文本信息 + /// + /// + public override string ToString() + { + return string.Format("持仓量:{0},挂开仓量:{1},挂平仓量:{2},开仓手数累计:{3}", + Qty, FrozenOpen, FrozenClose, CumOpenQty); + } + /// + /// 新增开仓订单 + /// + /// 开仓数量 + public void NewOrderOpen(double Qty) + { + FrozenClose += Qty;//挂平仓量+开仓手数 + } + /// + /// 新增平仓订单 + /// + /// 平仓数量 + public void NewOrderClose(double Qty) + { + FrozenClose += Qty;//挂平仓量+开仓手数 + } + /// + /// 新增平今订单 + /// + /// 平今数量 + public void NewOrderCloseToday(double Qty) + { + FrozenCloseToday += Qty;//挂平今数量变动 + FrozenClose += Qty;//挂平仓量变动 + } + /// + /// 填充开仓 + /// + /// + /// + public void FilledOpen(double LastQty, double LastPrice) + { + Qty += LastQty; + QtyToday += LastQty; + FrozenOpen -= LastQty; + CumOpenQty += LastQty; + HoldingCost += LastPrice * LastQty; + } + /// + /// 填充平仓 + /// + /// + /// + public void FilledClose(double LastQty, double LastPrice) + { + Qty -= LastQty; + FrozenClose -= LastQty; + if (Qty == 0) + { + HoldingCost = 0; + } + else + { + HoldingCost -= LastPrice * LastQty; + } + } + /// + /// 填充平今仓 + /// + /// + /// + public void FilledCloseToday(double LastQty, double LastPrice) + { + Qty -= LastQty;// 实际持仓量 - 平今仓订单的数量 + QtyToday -= LastQty;//实际持今仓量 - 平今仓订单的数量 + FrozenClose -= LastQty;//挂平仓量 - 平今仓订单的数量 + FrozenCloseToday -= LastQty;//挂平今量 - 平今仓订单的数量 + //重新计算持仓成本 + if (Qty == 0) + { + HoldingCost = 0; + } + else + { + HoldingCost -= LastPrice * LastQty;//减去平仓的成本 + } + } + /// + /// 拒绝订单开仓 + /// + /// + public void OrderRejectedOpen(double LeavesQty) + { + FrozenOpen -= LeavesQty; + } + /// + /// 拒绝订单平仓 + /// + /// + public void OrderRejectedClose(double LeavesQty) + { + FrozenClose -= LeavesQty; + } + /// + /// 拒绝订单平今仓 + /// + /// + public void OrderRejectedCloseToday(double LeavesQty) + { + FrozenCloseToday -= LeavesQty; + FrozenClose -= LeavesQty; + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Helper/PriceHelper.cs b/Demo/QuantBox.OQ.Demo/Helper/PriceHelper.cs index cac1b23..7a1c2d6 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/PriceHelper.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/PriceHelper.cs @@ -6,10 +6,22 @@ namespace QuantBox.OQ.Demo.Helper { + /// + /// 价格助手 + /// public class PriceHelper { + /// + /// 价格上限 + /// public double UpperLimitPrice { get; private set; } + /// + /// 价格下限 + /// public double LowerLimitPrice { get; private set; } + /// + /// Tick最小变量数量 + /// public double TickSize { get; private set; } public PriceHelper(double TickSize) @@ -27,7 +39,12 @@ public PriceHelper(double UpperLimitPrice, this.LowerLimitPrice = LowerLimitPrice; this.TickSize = TickSize; } - + /// + /// 获取价格水平,取TickSize的整数倍 + /// + /// 价格 + /// 买卖方向 + /// 价格 public int GetLevelByPrice(double price, OrderSide Side) { price = Math.Min(price, UpperLimitPrice); @@ -36,17 +53,31 @@ public int GetLevelByPrice(double price, OrderSide Side) int index = (int)((Side == OrderSide.Buy) ? Math.Ceiling(price / TickSize) : Math.Floor(price / TickSize)); return index; } - + /// + /// 获得价格 + /// + /// 价格 + /// public double GetPriceByLevel(int level) { - return level * TickSize; + return level * TickSize;//TickSize为每一跳的价格 } - + /// + /// 修正价格水平 + /// + /// + /// + /// public double FixPrice(double price, OrderSide Side) { return GetPriceByLevel(GetLevelByPrice(price, Side)); } - + /// + /// 获得匹配的价格 + /// + /// + /// + /// public double GetMatchPrice(Strategy strategy, OrderSide side) { Quote quote = strategy.Quote; diff --git a/Demo/QuantBox.OQ.Demo/Helper/TimeHelper.cs b/Demo/QuantBox.OQ.Demo/Helper/TimeHelper.cs index 871af99..ca02876 100644 --- a/Demo/QuantBox.OQ.Demo/Helper/TimeHelper.cs +++ b/Demo/QuantBox.OQ.Demo/Helper/TimeHelper.cs @@ -13,11 +13,22 @@ public enum EnumTradingTime COMMODITY_0230, // 黄金、白银 COMMODITY_0100, } - + /// + /// 时间助手 + /// public class TimeHelper { + /// + /// 交易时间 + /// public int[] WorkingTime; + /// + /// 结束时间 + /// public int EndOfDay { get; private set; } + /// + /// 开始时间 + /// public int BeginOfDay { get; private set; } public int[] WorkingTime_Financial = { 915, 1130, 1300, 1515 }; //IF,TF,IO @@ -25,14 +36,17 @@ public class TimeHelper public int[] WorkingTime_Commodity_0230 = { 0, 230, 900, 1015, 1030, 1130, 1330, 1500, 2100, 2400 };//au,ag public int[] WorkingTime_Commodity_0100 = { 0, 100, 900, 1015, 1030, 1130, 1330, 1500, 2100, 2400 };//铜、铝、铅、锌 - private int EndOfDay_Financial = 1515; //IF - private int EndOfDay_Commodity = 1500; //商品 + private int EndOfDay_Financial = 1515; //IF 结束时间 + private int EndOfDay_Commodity = 1500; //商品结束时间 - private int BeginOfDay_Financial = 915; - private int BeginOfDay_Commodity = 900; + private int BeginOfDay_Financial = 915;//上期所的开始时间 + private int BeginOfDay_Commodity = 900;//商品的开始时间 private int BeginOfDay_Commodity_0230 = 2100; private int BeginOfDay_Commodity_0100 = 2100; - + /// + /// 确定开收盘时间 + /// 构造函数,根据合约属性确定开盘、收盘和交易时间 + /// public TimeHelper(EnumTradingTime tt) { switch(tt) @@ -59,21 +73,32 @@ public TimeHelper(EnumTradingTime tt) break; } } - + /// + /// 构造函数:根据合约ID确定开盘、收盘、交易时间 + /// + /// public TimeHelper(string instrument):this(GetTradingTime(instrument)) { } - + /// + /// + /// + /// 开始时间 + /// 结束时间 public TimeHelper(int[] workingTime,int beginOfDay,int ennOfDay) { WorkingTime = workingTime; BeginOfDay = beginOfDay; EndOfDay = ennOfDay; } - + /// + /// 合约号前缀获取交易所时间 + /// + /// 合约 + /// 返回合约属性 public static EnumTradingTime GetTradingTime(string instrument) { - string prefix = instrument.Substring(0, 2); + string prefix = instrument.Substring(0, 2);//得到前缀2个字符 switch(prefix) { case "IF": @@ -95,7 +120,11 @@ public static EnumTradingTime GetTradingTime(string instrument) return EnumTradingTime.COMMODITY; } } - + /// + /// 确定是否Trading时间 + /// + /// + /// public bool IsTradingTime(int time) { int index = -1; @@ -113,24 +142,35 @@ public bool IsTradingTime(int time) if (index % 2 == 0) { - // 交易时段 + // Trading时段 return true; } - // 非交易时段 + // 非Trading时段 return false; } - + /// + /// 把时间换成为数字表示。如915表示9:15分 + /// + /// + /// public int GetTime(DateTime dt) { return dt.Hour * 100 + dt.Minute; } - + /// + /// 确定是否Trading时间 + /// + /// 时间参数 + /// public bool IsTradingTime(DateTime dt) { return IsTradingTime(GetTime(dt)); } - + /// + /// 是否交易时间 + /// + /// public bool IsTradingTime() { return IsTradingTime(Clock.Now); diff --git a/Demo/QuantBox.OQ.Demo/Helper/TimeHelper.cs.orig b/Demo/QuantBox.OQ.Demo/Helper/TimeHelper.cs.orig new file mode 100644 index 0000000..adba25c --- /dev/null +++ b/Demo/QuantBox.OQ.Demo/Helper/TimeHelper.cs.orig @@ -0,0 +1,219 @@ +using OpenQuant.API; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace QuantBox.OQ.Demo.Helper +{ + public enum EnumTradingTime + { + FINANCIAL, // 金融 + COMMODITY, // 商品 + COMMODITY_0230, // 黄金、白银 + COMMODITY_0100, + } + /// + /// 时间助手 + /// + public class TimeHelper + { + /// + /// 交易时间 + /// + public int[] WorkingTime; + /// + /// 结束时间 + /// + public int EndOfDay { get; private set; } + /// + /// 开始时间 + /// + public int BeginOfDay { get; private set; } + + public int[] WorkingTime_Financial = { 915, 1130, 1300, 1515 }; //IF,TF,IO + public int[] WorkingTime_Commodity = { 900, 1015, 1030, 1130, 1330, 1500 }; //商品 + public int[] WorkingTime_Commodity_0230 = { 0, 230, 900, 1015, 1030, 1130, 1330, 1500, 2100, 2400 };//au,ag + public int[] WorkingTime_Commodity_0100 = { 0, 100, 900, 1015, 1030, 1130, 1330, 1500, 2100, 2400 };//铜、铝、铅、锌 + + private int EndOfDay_Financial = 1515; //IF 结束时间 + private int EndOfDay_Commodity = 1500; //商品结束时间 + + private int BeginOfDay_Financial = 915;//上期所的开始时间 + private int BeginOfDay_Commodity = 900;//商品的开始时间 + private int BeginOfDay_Commodity_0230 = 2100; + private int BeginOfDay_Commodity_0100 = 2100; + /// +<<<<<<< HEAD + /// 确定开收盘时间 + /// 构造函数,根据合约属性确定开盘、收盘和交易时间 + /// +======= + /// 时间助手,根据所属交易所的类型确定交易时间 + /// + /// +>>>>>>> ea6f02b26addf16158c8567adeedbd21d778379a + public TimeHelper(EnumTradingTime tt) + { + switch(tt) + { + case EnumTradingTime.FINANCIAL: + WorkingTime = WorkingTime_Financial; + EndOfDay = EndOfDay_Financial; + BeginOfDay = BeginOfDay_Financial; + break; + case EnumTradingTime.COMMODITY: + WorkingTime = WorkingTime_Commodity; + EndOfDay = EndOfDay_Commodity; + BeginOfDay = BeginOfDay_Commodity; + break; + case EnumTradingTime.COMMODITY_0230: + WorkingTime = WorkingTime_Commodity_0230; + EndOfDay = EndOfDay_Commodity; + BeginOfDay = BeginOfDay_Commodity_0230; + break; + case EnumTradingTime.COMMODITY_0100: + WorkingTime = WorkingTime_Commodity_0100; + EndOfDay = EndOfDay_Commodity; + BeginOfDay = BeginOfDay_Commodity_0100; + break; + } + } + /// + /// 构造函数:根据合约ID确定开盘、收盘、交易时间 + /// + /// + public TimeHelper(string instrument):this(GetTradingTime(instrument)) + { + } + /// +<<<<<<< HEAD + /// 构造函数:设置开盘、收盘、交易时间 + /// + /// +======= + /// 时间助手构造函数 + /// + /// 交易时间 + /// 开始时间 + /// 结束时间 +>>>>>>> ea6f02b26addf16158c8567adeedbd21d778379a + public TimeHelper(int[] workingTime,int beginOfDay,int ennOfDay) + { + WorkingTime = workingTime; + BeginOfDay = beginOfDay; + EndOfDay = ennOfDay; + } + /// +<<<<<<< HEAD + /// 获取指定合约的Trading时间 + /// + /// 合约 + /// 返回合约属性 +======= + /// 合约号前缀获取交易所时间 + /// + /// + /// +>>>>>>> ea6f02b26addf16158c8567adeedbd21d778379a + public static EnumTradingTime GetTradingTime(string instrument) + { + string prefix = instrument.Substring(0, 2);//得到前缀2个字符 + switch(prefix) + { + case "IF": + case "TF": + case "IO": + case "IH": + case "IC": + case "HO": + return EnumTradingTime.FINANCIAL; + case "au": + case "ag": + return EnumTradingTime.COMMODITY_0230; + case "cu": + case "al": + case "pb": + case "zn": + return EnumTradingTime.COMMODITY_0100; + default: + return EnumTradingTime.COMMODITY; + } + } + /// +<<<<<<< HEAD + /// 确定是否Trading时间 + /// + /// +======= + /// 时否交易时间 + /// + /// 整型参数 +>>>>>>> ea6f02b26addf16158c8567adeedbd21d778379a + /// + public bool IsTradingTime(int time) + { + int index = -1; + for (int i = 0; i < WorkingTime.Length; ++i) + { + if (time < WorkingTime[i]) + { + break; + } + else + { + index = i; + } + } + + if (index % 2 == 0) + { + // Trading时段 + return true; + } + + // 非Trading时段 + return false; + } + /// +<<<<<<< HEAD + /// 把时间换成为数字表示。如915表示9:15分 +======= + /// 得到数字表示的时间,形如9:15表示为915 +>>>>>>> ea6f02b26addf16158c8567adeedbd21d778379a + /// + /// + /// + public int GetTime(DateTime dt) + { + return dt.Hour * 100 + dt.Minute; + } + /// +<<<<<<< HEAD + /// 确定是否Trading时间 + /// + /// +======= + /// 时否交易时间 + /// + /// 时间参数 +>>>>>>> ea6f02b26addf16158c8567adeedbd21d778379a + /// + public bool IsTradingTime(DateTime dt) + { + return IsTradingTime(GetTime(dt)); + } + /// +<<<<<<< HEAD + /// 确定是否Trading时间 +======= + /// 是否交易时间 +>>>>>>> ea6f02b26addf16158c8567adeedbd21d778379a + /// + /// + public bool IsTradingTime() + { + return IsTradingTime(Clock.Now); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Indicator/DPO1.cs b/Demo/QuantBox.OQ.Demo/Indicator/DPO1.cs index e697488..14f5f4d 100644 --- a/Demo/QuantBox.OQ.Demo/Indicator/DPO1.cs +++ b/Demo/QuantBox.OQ.Demo/Indicator/DPO1.cs @@ -20,9 +20,9 @@ public class DPO1 : UserIndicator public DPO1(ISeries series, int length, BarData barData) : base(series) { - this.length = length; - this.option = barData; - this.Name = "DPO"; + this.length = length;//长度 + this.option = barData;//bar类型 + this.Name = "DPO";//名称 } public override double Calculate(int index) diff --git a/Demo/QuantBox.OQ.Demo/Indicator/KaufmanAMA.cs b/Demo/QuantBox.OQ.Demo/Indicator/KaufmanAMA.cs index 684d869..65a02fd 100644 --- a/Demo/QuantBox.OQ.Demo/Indicator/KaufmanAMA.cs +++ b/Demo/QuantBox.OQ.Demo/Indicator/KaufmanAMA.cs @@ -1,73 +1,73 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -namespace QuantBox.OQ.Demo.Indicator -{ - /// - /// Kaufman自适应移动平均 - /// - public class KaufmanAMA : UserIndicator - { - int n, p, q; - // 效率系数 - public TimeSeries ER = new TimeSeries("ER"); - - public KaufmanAMA(ISeries series, int n, int p, int q) - : base(series) - { - this.n = n; - this.p = p; - this.q = q; - this.Name = string.Format("KaufmanAMA({0},{1},{2})", n, p, q); - } - - public override double Calculate(int index) - { - int j = index - n; - if (j < 0) - return double.NaN; - - DateTime dt = Input.GetDateTime(index); - - double DIRECTION = Math.Abs(Input[index, BarData.Close] - Input[j, BarData.Close]); - - double VOLATILITY = 0; - for (int i = j; i < index; ++i) - { - VOLATILITY += Math.Abs(Input[i + 1, BarData.Close] - Input[i, BarData.Close]); - } - //return VOLATILITY; - - double _ER = DIRECTION / VOLATILITY; //{EFFICIENCY RATIO是AMA系统中最重要的指标,比值越大,趋势越明显} - if (VOLATILITY == 0) - { - _ER = 1; - } - ER.Add(dt, _ER); - //return ER; - - double FSC = 2.0 / (1.0 + p); // {快速平滑常数} - double SSC = 2.0 / (1.0 + q); // {慢速平滑常数} - double SC = _ER * (FSC - SSC) + SSC; //{等价于SC=ER*FSC+(1-ER)*SSC,指数平滑序列} - double SCSQ = SC * SC; - - double db = Input[index, BarData.Close]; - - if (j == 0) - { - } - else - { - db = SCSQ * db + (1 - SCSQ) * this[j - 1]; - } - - return db; - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +namespace QuantBox.OQ.Demo.Indicator +{ + /// + /// Kaufman自适应移动平均 + /// + public class KaufmanAMA : UserIndicator + { + int n, p, q; + // 效率系数 + public TimeSeries ER = new TimeSeries("ER"); + + public KaufmanAMA(ISeries series, int n, int p, int q) + : base(series) + { + this.n = n; + this.p = p; + this.q = q; + this.Name = string.Format("KaufmanAMA({0},{1},{2})", n, p, q); + } + + public override double Calculate(int index) + { + int j = index - n; + if (j < 0) + return double.NaN; + + DateTime dt = Input.GetDateTime(index); + + double DIRECTION = Math.Abs(Input[index, BarData.Close] - Input[j, BarData.Close]); + + double VOLATILITY = 0; + for (int i = j; i < index; ++i) + { + VOLATILITY += Math.Abs(Input[i + 1, BarData.Close] - Input[i, BarData.Close]); + } + //return VOLATILITY; + + double _ER = DIRECTION / VOLATILITY; //{EFFICIENCY RATIO是AMA系统中最重要的指标,比值越大,趋势越明显} + if (VOLATILITY == 0) + { + _ER = 1; + } + ER.Add(dt, _ER); + //return ER; + + double FSC = 2.0 / (1.0 + p); // {快速平滑常数} + double SSC = 2.0 / (1.0 + q); // {慢速平滑常数} + double SC = _ER * (FSC - SSC) + SSC; //{等价于SC=ER*FSC+(1-ER)*SSC,指数平滑序列} + double SCSQ = SC * SC; + + double db = Input[index, BarData.Close]; + + if (j == 0) + { + } + else + { + db = SCSQ * db + (1 - SCSQ) * this[j - 1]; + } + + return db; + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Indicator/Test/DynamicBBU_code.cs b/Demo/QuantBox.OQ.Demo/Indicator/Test/DynamicBBU_code.cs index 81a3176..5d2e531 100644 --- a/Demo/QuantBox.OQ.Demo/Indicator/Test/DynamicBBU_code.cs +++ b/Demo/QuantBox.OQ.Demo/Indicator/Test/DynamicBBU_code.cs @@ -1,41 +1,41 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -namespace QuantBox.OQ.Demo.Indicator.Test -{ - public class DynamicBBU_code : Strategy - { - DynamicBBU dbbu; - TimeSeries lengths = new TimeSeries("Lengths"); - - public override void OnStrategyStart() - { - dbbu = new DynamicBBU(lengths, Bars, 2, BarData.Close); - - Draw(dbbu, 0); - Draw(dbbu.BBL, 0); - Draw(dbbu.SMA, 0); - Draw(dbbu.VAR, 2); - - Draw(lengths, 3); - } - - - - public override void OnBar(Bar bar) - { - - // 这个地方是关键 - lengths.Add(bar.DateTime, 5); - - // 别的就自己写吧 - - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +namespace QuantBox.OQ.Demo.Indicator.Test +{ + public class DynamicBBU_code : Strategy + { + DynamicBBU dbbu; + TimeSeries lengths = new TimeSeries("Lengths"); + + public override void OnStrategyStart() + { + dbbu = new DynamicBBU(lengths, Bars, 2, BarData.Close); + + Draw(dbbu, 0); + Draw(dbbu.BBL, 0); + Draw(dbbu.SMA, 0); + Draw(dbbu.VAR, 2); + + Draw(lengths, 3); + } + + + + public override void OnBar(Bar bar) + { + + // 这个地方是关键 + lengths.Add(bar.DateTime, 5); + + // 别的就自己写吧 + + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Module/TargetOrderBookModule.cs b/Demo/QuantBox.OQ.Demo/Module/TargetOrderBookModule.cs index 3f68ecd..797d7ef 100644 --- a/Demo/QuantBox.OQ.Demo/Module/TargetOrderBookModule.cs +++ b/Demo/QuantBox.OQ.Demo/Module/TargetOrderBookModule.cs @@ -8,6 +8,9 @@ namespace QuantBox.OQ.Demo.Module { + /// + /// 目标挂单助手 + /// public class TargetOrderBookModule : TargetPositionModule { class CopyOrder diff --git a/Demo/QuantBox.OQ.Demo/Module/TargetPositionModule.cs b/Demo/QuantBox.OQ.Demo/Module/TargetPositionModule.cs index 6b0d2e1..ce09f67 100644 --- a/Demo/QuantBox.OQ.Demo/Module/TargetPositionModule.cs +++ b/Demo/QuantBox.OQ.Demo/Module/TargetPositionModule.cs @@ -1,562 +1,606 @@ -using OpenQuant.API; -using QuantBox.OQ.Demo.Helper; -using QuantBox.OQ.Extensions; -using QuantBox.OQ.Extensions.OrderText; -using System; - -namespace QuantBox.OQ.Demo.Module -{ - public class TargetPositionModule : Strategy - { - public DualPosition DualPosition; - /// - /// 目标仓位 - /// - public double TargetPosition = 0; - /// - /// 每笔最大手数 - /// - [Parameter("每笔最大手数", "TargetPositionModule")] - public double MaxQtyPerLot = 5; - /// - /// 小于等于此数量的开仓单自动以市价发送 - /// - [Parameter("小于等于此数量的开仓单自动以市价发送", "TargetPositionModule")] - public double MarketOpenQtyThreshold = 5; - /// - /// 小于等于此数量的平仓单自动以市价发送 - /// - [Parameter("小于等于此数量的平仓单自动以市价发送", "TargetPositionModule")] - public double MarketCloseQtyThreshold = 20; - /// - /// 对手价上加N跳下单 - /// - [Parameter("对手价上加N跳下单", "TargetPositionModule")] - public int Jump = 2; - - protected TimeHelper TimeHelper; - protected PriceHelper PriceHelper; - protected CloseTodayHelper CloseTodayHelper; - - protected TextCommon TextParameter; - - /// - /// 入场后的最高价,用于跟踪止损 - /// - public double HighestAfterEntry = double.MinValue; - /// - /// 入场后的最低价,用于跟踪止损 - /// - public double LowestAfterEntry = double.MaxValue; - - /// - /// 在进行各项计算时到底是使用信号持仓还是实盘持仓呢? - /// - /// - public virtual double GetCurrentQty() - { - // 各项处理时使用实盘持仓 - return DualPosition.NetQty; - // 各项处理时使用信号持仓 - //return TargetPosition; - } - - public virtual double GetLongAvgPrice() - { - return DualPosition.Long.AvgPrice; - } - - public virtual double GetShortAvgPrice() - { - return DualPosition.Short.AvgPrice; - } - - /// - /// 计算入场后的最高价与最低价 - /// - /// - public void HiLoAfterEntry(double price) - { - double qty = GetCurrentQty(); - if (qty == 0) - { - HighestAfterEntry = double.MinValue; - LowestAfterEntry = double.MaxValue; - } - else - { - HighestAfterEntry = Math.Max(HighestAfterEntry, price); - LowestAfterEntry = Math.Min(LowestAfterEntry, price); - } - } - - public override void OnStrategyStart() - { - TimeHelper = new TimeHelper(Instrument.Symbol); - PriceHelper = new PriceHelper(Instrument.TickSize); - TextParameter = new TextCommon() { OpenClose = EnumOpenClose.OPEN }; - CloseTodayHelper = new CloseTodayHelper(EnumExchangeID.SHFE); - - DualPosition = new DualPosition(Instrument.Symbol); - DualPosition.Sell.PriceHelper = PriceHelper; - DualPosition.Buy.PriceHelper = PriceHelper; - DualPosition.CloseTodayHelper = CloseTodayHelper; - - TargetPosition = 0; - DualPosition.Long.Qty = 0; - DualPosition.Long.QtyToday = 0; - DualPosition.Short.Qty = 0; - DualPosition.Short.QtyToday = 0; - } - - public override void OnTrade(Trade trade) - { - //lock(this) - { - Process(); - } - HiLoAfterEntry(trade.Price); - } - - public override void OnQuote(Quote quote) - { - //lock(this) - { - Process(); - } - - // 如果只有Quote数据,如何更新? - // 那就会不用这个目标仓位助手了 - //if(!DataRequests.HasTradeRequest) - //{ - //} - } - - public override void OnBarOpen(Bar bar) - { - //lock(this) - { - Process(); - } - HiLoAfterEntry(bar.Open); - } - - public override void OnBar(Bar bar) - { - //lock(this) - { - Process(); - } - HiLoAfterEntry(bar.Close); - } - - /// - /// 进行下单,最小手续费处理原则 - /// - public virtual void Process() - { - // 非交易时段,不处理 - if (!TimeHelper.IsTradingTime()) - { - return; - } - - double qty = 0; - OrderSide Side = OrderSide.Buy; - TextParameter.OpenClose = EnumOpenClose.OPEN; - - lock(this) - { - // 计算仓差 - double dif = TargetPosition - DualPosition.NetQty; - - if (dif == 0)// 持仓量相等 - { - // 把所有的挂单全撤了 - DualPosition.Cancel(); - return; - } - else if (dif > 0 && !DualPosition.IsPending)// 表示要增加净持仓 - { - // 是否有在途增仓订单,超数了 - // 是否有在途减仓订单,全取消息 - qty = dif; - Side = OrderSide.Buy; - - EnumOpenClose oc = EnumOpenClose.CLOSE; - double q = CloseTodayHelper.GetCloseAndQty(DualPosition.Short, out oc); - if (q > 0) - { - // 按最小数量进行平仓 - qty = Math.Min(qty, q); - TextParameter.OpenClose = oc; - } - } - else if (!DualPosition.IsPending) // 减少净持仓 - { - qty = -dif; - Side = OrderSide.Sell; - - EnumOpenClose oc = EnumOpenClose.CLOSE; - double q = CloseTodayHelper.GetCloseAndQty(DualPosition.Long, out oc); - if (q > 0) - { - // 按最小数量进行平仓 - qty = Math.Min(qty, q); - TextParameter.OpenClose = oc; - } - } - - if (qty > 0) - { - qty = Math.Min(qty, MaxQtyPerLot); - - // 下单 - SendOrder(Side, qty); - } - } - } - - /// - /// 下单 - /// - /// - /// - public void SendOrder(OrderSide side, double qty) - { - if (!TimeHelper.IsTradingTime()) - { - return; - } - - if (qty <= 0) - { - return; - } - - // 为减少滑点,对数量少的单子直接市价单 - bool bMarketOrder = false; - if (EnumOpenClose.OPEN == TextParameter.OpenClose) - { - if (qty <= MarketOpenQtyThreshold) - bMarketOrder = true; - } - else - { - if (qty <= MarketCloseQtyThreshold) - bMarketOrder = true; - } - - //lock(this) - { - if (bMarketOrder) - { - SendMarketOrder(side, qty, TextParameter.ToString()); - } - else - { - SendLimitOrder(side, qty, PriceHelper.GetMatchPrice(this, side, Jump), TextParameter.ToString()); - } - } - } - - /// - /// 重新发单 - /// - /// - public void ResendOrder(Order order) - { - SendOrder(order.Side, order.LeavesQty); - } - - public override void OnOrderPartiallyFilled(Order order) - { - double LastPrice = order.LastPrice; - //lock(this) - { - DualPosition.Filled(order); - - // 单子部分成交,不做操作,等单子完全执行完 - // 等交易完,会有问题,一直挂在上面不操作,新单子也过不来 - //Process(); - } - HiLoAfterEntry(LastPrice); - } - - public override void OnOrderFilled(Order order) - { - double LastPrice = order.LastPrice; - //lock(this) - { - DualPosition.Filled(order); - - // 检查仓位是否正确,是否要发新单 - //Process(); - } - HiLoAfterEntry(LastPrice); - } - - public override void OnNewOrder(Order order) - { - //lock(this) - { - DualPosition.NewOrder(order); - - // 得加定时器,一定的时间内没有成交完全应当撤单重发,目前没有加这一功能 - } - } - - public override void OnOrderRejected(Order order) - { - double LeavesQty = order.LeavesQty; - double flag = order.Side == OrderSide.Buy ? 1 : -1; - EnumOpenClose OpenClose = DualPosition.OrderRejected(order); - - lock(this) - { - if (EnumOpenClose.OPEN == OpenClose) - { - // 开仓被拒绝,不再新开仓 - // 有可能是钱不够 - // 有可能是超出持仓限制 - // 有可能是非交易时间 - TargetPosition -= flag * LeavesQty; - return; - } - - EnumError error = TextResponse.FromText(order.Text); - - // 无法平仓,不重发单 - // 能出现这个问题是持仓计算错误,这已经是策略持仓计算错误了 - if (error == EnumError.OVER_CLOSETODAY_POSITION - || error == EnumError.OVER_CLOSEYESTERDAY_POSITION - || error == EnumError.OVER_CLOSE_POSITION) - { - TargetPosition -= flag * LeavesQty; - return; - } - - // 当前状态禁止此项操作,时间不对,应当等下次操作 - } - } - - public override void OnOrderCancelled(Order order) - { - //lock(this) - { - DualPosition.OrderCancelled(order); - - // 这个地方会影响做市商的挂单功能 - //ResendOrder(order); - } - } - - public override void OnOrderCancelReject(Order order) - { - // 撤单被拒绝,暂不操作 - } - - /// - /// 根据入场后的最高与最低价,跟踪止损 - /// - /// - /// - /// - /// 止损了返止损前持仓,可用于后面的反手 - public virtual double TrailingStop(double currentPrice, double level, StopMode mode,string text) - { - //lock(this) - { - double qty = GetCurrentQty(); - double stop; - if (qty > double.Epsilon) - { - if (StopMode.Percent == mode) - { - stop = HighestAfterEntry * (1.0 - level); - } - else - { - stop = HighestAfterEntry - level; - } - if (currentPrice < stop) - { - TargetPosition = 0; - TextParameter.Text = string.Format("跟踪止损 - 最高{0},止损{1}>当前{2}|{3}", - HighestAfterEntry, stop, currentPrice, - text); - return qty; - } - } - else if (qty < -double.Epsilon) - { - if (StopMode.Percent == mode) - { - stop = LowestAfterEntry * (1.0 + level); - } - else - { - stop = LowestAfterEntry + level; - } - - if (currentPrice > stop) - { - TargetPosition = 0; - TextParameter.Text = string.Format("跟踪止损 - 最低{0},止损{1}<当前{2}|{3}", - HighestAfterEntry, stop, currentPrice, - text); - return qty; - } - } - - return 0; - } - } - - /// - /// 从入场均价开始算起,固定点位止损 - /// - /// - /// - /// - /// 止损了返止损前持仓,可用于后面的反手 - public virtual double FixedStop(double currentPrice, double level, StopMode mode, string text) - { - //lock(this) - { - double qty = GetCurrentQty(); - double stop; - if (qty > double.Epsilon) - { - if (StopMode.Percent == mode) - { - stop = GetLongAvgPrice() * (1.0 - level); - } - else - { - stop = GetLongAvgPrice() - level; - } - if (currentPrice < stop) - { - TargetPosition = 0; - TextParameter.Text = string.Format("固定止损 - 多头均价{0},止损{1}>当前{2}|{3}", - GetLongAvgPrice(), stop, currentPrice, - text); - return qty; - } - } - else if (qty < -double.Epsilon) - { - if (StopMode.Percent == mode) - { - stop = GetShortAvgPrice() * (1.0 + level); - } - else - { - stop = GetShortAvgPrice() + level; - } - - if (currentPrice > stop) - { - TargetPosition = 0; - TextParameter.Text = string.Format("固定止损 - 空头均价{0},止损{1}<当前{2}|{3}", - GetShortAvgPrice(), stop, currentPrice, - text); - return qty; - } - } - return 0; - } - } - - public virtual double TakeProfit(double currentPrice, double level, StopMode mode, string text) - { - //lock(this) - { - double qty = GetCurrentQty(); - double stop; - if (qty > double.Epsilon) - { - if (StopMode.Percent == mode) - { - stop = GetLongAvgPrice() * (1.0 + level); - } - else - { - stop = GetLongAvgPrice() + level; - } - if (currentPrice > stop) - { - TargetPosition = 0; - TextParameter.Text = string.Format("固定止赢 - 多头均价{0},止赢{1}<当前{2}|{3}", - GetLongAvgPrice(), stop, currentPrice, - text); - return qty; - } - } - else if (qty < -double.Epsilon) - { - if (StopMode.Percent == mode) - { - stop = GetShortAvgPrice() * (1.0 - level); - } - else - { - stop = GetShortAvgPrice() - level; - } - - if (currentPrice < stop) - { - TargetPosition = 0; - TextParameter.Text = string.Format("固定止赢 - 空头均价{0},止赢{1}>当前{2}|{3}", - GetShortAvgPrice(), stop, currentPrice, - text); - return qty; - } - } - return 0; - } - } - - /// - /// 尾盘清仓 - /// - /// 返回上次持仓量 - public virtual double ExitOnClose(double seconds,string text) - { - //lock(this) - { - double qty = GetCurrentQty(); - if (TimeHelper.GetTime(Clock.Now.AddSeconds(seconds)) >= TimeHelper.EndOfDay) - { - TargetPosition = 0; - TextParameter.Text = string.Format("尾盘,清仓|{0}", text); - return qty; - } - return 0; - } - } - - public virtual void ChangeTradingDay() - { - if (TimeHelper.BeginOfDay > TimeHelper.EndOfDay) - { - // 夜盘 - if (TimeHelper.GetTime(Clock.Now) > TimeHelper.EndOfDay - && TimeHelper.GetTime(Clock.Now) < TimeHelper.BeginOfDay) - { - DualPosition.ChangeTradingDay(); - } - } - else - { - if (TimeHelper.GetTime(Clock.Now) > TimeHelper.EndOfDay - || TimeHelper.GetTime(Clock.Now) < TimeHelper.BeginOfDay) - { - DualPosition.ChangeTradingDay(); - } - } - } - } - -} +using OpenQuant.API; +using QuantBox.OQ.Demo.Helper; +using QuantBox.OQ.Extensions; +using QuantBox.OQ.Extensions.OrderText; +using System; + +namespace QuantBox.OQ.Demo.Module +{ + /// + /// 目标仓位助手 + /// + public class TargetPositionModule : Strategy + { + public DualPosition DualPosition; + /// + /// 目标仓位 + /// + public double TargetPosition = 0; + /// + /// 每笔最大手数 + /// + [Parameter("每笔最大手数", "TargetPositionModule")] + public double MaxQtyPerLot = 5; + /// + /// 小于等于此数量的开仓单自动以市价发送 + /// + [Parameter("小于等于此数量的开仓单自动以市价发送", "TargetPositionModule")] + public double MarketOpenQtyThreshold = 5; + /// + /// 小于等于此数量的平仓单自动以市价发送 + /// + [Parameter("小于等于此数量的平仓单自动以市价发送", "TargetPositionModule")] + public double MarketCloseQtyThreshold = 20; + /// + /// 对手价上加N跳下单 + /// + [Parameter("对手价上加N跳下单", "TargetPositionModule")] + public int Jump = 2; + + protected TimeHelper TimeHelper;//时间助手 + protected PriceHelper PriceHelper;//价格助手 + protected CloseTodayHelper CloseTodayHelper;//平今仓助手 + + protected TextCommon TextParameter;//文本参数,显示交易命令参数 + + /// + /// 入场后的最高价,用于跟踪止损 + /// + public double HighestAfterEntry = double.MinValue; + /// + /// 入场后的最低价,用于跟踪止损 + /// + public double LowestAfterEntry = double.MaxValue; + + /// + /// 获取当前持仓 + /// 在进行各项计算时到底是使用信号持仓还是实盘持仓呢? + /// + /// + public virtual double GetCurrentQty() + { + // 各项处理时使用实盘持仓 + return DualPosition.NetQty; + // 各项处理时使用信号持仓 + //return TargetPosition; + } + /// + /// 取得多头持仓平均成本 + /// + /// + public virtual double GetLongAvgPrice() + { + return DualPosition.Long.AvgPrice; + } + /// + /// 取得空头持仓平均成本 + /// + /// + public virtual double GetShortAvgPrice() + { + return DualPosition.Short.AvgPrice; + } + + /// + /// 计算入场后的最高价与最低价 + /// + /// + public void HiLoAfterEntry(double price) + { + double qty = GetCurrentQty(); + if (qty == 0) + { + HighestAfterEntry = double.MinValue; + LowestAfterEntry = double.MaxValue; + } + else + { + HighestAfterEntry = Math.Max(HighestAfterEntry, price); + LowestAfterEntry = Math.Min(LowestAfterEntry, price); + } + } + + public override void OnStrategyStart() + { + TimeHelper = new TimeHelper(Instrument.Symbol); + PriceHelper = new PriceHelper(Instrument.TickSize); + TextParameter = new TextCommon() { OpenClose = EnumOpenClose.OPEN }; + CloseTodayHelper = new CloseTodayHelper(EnumExchangeID.SHFE); + + DualPosition = new DualPosition(Instrument.Symbol); + DualPosition.Sell.PriceHelper = PriceHelper; + DualPosition.Buy.PriceHelper = PriceHelper; + DualPosition.CloseTodayHelper = CloseTodayHelper; + + TargetPosition = 0;//仓位初始化 + DualPosition.Long.Qty = 0; + DualPosition.Long.QtyToday = 0; + DualPosition.Short.Qty = 0; + DualPosition.Short.QtyToday = 0; + } + + public override void OnTrade(Trade trade) + { + //lock(this) + { + Process(); + } + HiLoAfterEntry(trade.Price); + } + + public override void OnQuote(Quote quote) + { + //lock(this) + { + Process(); + } + + // 如果只有Quote数据,如何更新? + // 那就会不用这个目标仓位助手了 + //if(!DataRequests.HasTradeRequest) + //{ + //} + } + /// + /// OpenBar事件 + /// + /// + public override void OnBarOpen(Bar bar) + { + //lock(this) + { + Process(); + } + HiLoAfterEntry(bar.Open); + } + + public override void OnBar(Bar bar) + { + //lock(this) + { + Process(); + } + HiLoAfterEntry(bar.Close); + } + + /// + /// 进行下单,最小手续费处理原则 + /// + public virtual void Process() + { + // 非交易时段,不处理 + if (!TimeHelper.IsTradingTime()) + { + return; + } + + double qty = 0; + OrderSide Side = OrderSide.Buy; + TextParameter.OpenClose = EnumOpenClose.OPEN; + + lock(this) + { + // 计算仓差 = 目标持仓 - 实际持仓(多头挂仓量-空头持仓量) + double dif = TargetPosition - DualPosition.NetQty; + + if (dif == 0)// 多仓=空仓,持仓量相等 + { + // 把所有的挂单全撤了 + DualPosition.Cancel(); + return; + } + else if (dif > 0 && !DualPosition.IsPending)// 表示要增加净持仓 + { + // 是否有在途增仓订单,超数了 + // 是否有在途减仓订单,全取消息 + qty = dif; + Side = OrderSide.Buy; + + EnumOpenClose oc = EnumOpenClose.CLOSE; + double q = CloseTodayHelper.GetCloseAndQty(DualPosition.Short, out oc); + if (q > 0) + { + // 按最小数量进行平仓 + qty = Math.Min(qty, q); + TextParameter.OpenClose = oc; + } + } + else if (!DualPosition.IsPending) // 减少净持仓 + { + qty = -dif; + Side = OrderSide.Sell; + + EnumOpenClose oc = EnumOpenClose.CLOSE; + double q = CloseTodayHelper.GetCloseAndQty(DualPosition.Long, out oc); + if (q > 0) + { + // 按最小数量进行平仓 + qty = Math.Min(qty, q); + TextParameter.OpenClose = oc; + } + } + + if (qty > 0) + { + qty = Math.Min(qty, MaxQtyPerLot); + + // 下单 + SendOrder(Side, qty); + } + } + } + + /// + /// 下单 + /// + /// + /// + public void SendOrder(OrderSide side, double qty) + { + if (!TimeHelper.IsTradingTime()) + { + return; + } + + if (qty <= 0) + { + return; + } + + // 为减少滑点,对数量少的单子直接市价单 + bool bMarketOrder = false; + if (EnumOpenClose.OPEN == TextParameter.OpenClose) + { + if (qty <= MarketOpenQtyThreshold) + bMarketOrder = true; + } + else + { + if (qty <= MarketCloseQtyThreshold) + bMarketOrder = true; + } + + //lock(this) + { + if (bMarketOrder) + { + SendMarketOrder(side, qty, TextParameter.ToString()); + } + else + { + SendLimitOrder(side, qty, PriceHelper.GetMatchPrice(this, side, Jump), TextParameter.ToString()); + } + } + } + + /// + /// 重新发单 + /// + /// + public void ResendOrder(Order order) + { + SendOrder(order.Side, order.LeavesQty); + } + + public override void OnOrderPartiallyFilled(Order order) + { + double LastPrice = order.LastPrice; + //lock(this) + { + DualPosition.Filled(order); + + // 单子部分成交,不做操作,等单子完全执行完 + // 等交易完,会有问题,一直挂在上面不操作,新单子也过不来 + //Process(); + } + HiLoAfterEntry(LastPrice); + } + + public override void OnOrderFilled(Order order) + { + double LastPrice = order.LastPrice; + //lock(this) + { + DualPosition.Filled(order); + + // 检查仓位是否正确,是否要发新单 + //Process(); + } + HiLoAfterEntry(LastPrice); + } + /// + /// 新增订单事件 + /// + /// + public override void OnNewOrder(Order order) + { + //lock(this) + { + DualPosition.NewOrder(order); + + // 得加定时器,一定的时间内没有成交完全应当撤单重发,目前没有加这一功能 + } + } + /// + /// 订单被拒绝事件 + /// + /// + public override void OnOrderRejected(Order order) + { + double LeavesQty = order.LeavesQty; + double flag = order.Side == OrderSide.Buy ? 1 : -1; + EnumOpenClose OpenClose = DualPosition.OrderRejected(order); + + lock(this) + { + if (EnumOpenClose.OPEN == OpenClose) + { + // 开仓被拒绝,不再新开仓 + // 有可能是钱不够 + // 有可能是超出持仓限制 + // 有可能是非交易时间 + TargetPosition -= flag * LeavesQty; + return; + } + + EnumError error = TextResponse.FromText(order.Text); + + // 无法平仓,不重发单 + // 能出现这个问题是持仓计算错误,这已经是策略持仓计算错误了 + if (error == EnumError.OVER_CLOSETODAY_POSITION + || error == EnumError.OVER_CLOSEYESTERDAY_POSITION + || error == EnumError.OVER_CLOSE_POSITION) + { + TargetPosition -= flag * LeavesQty; + return; + } + + // 当前状态禁止此项操作,时间不对,应当等下次操作 + } + } + /// + /// 订单被取消事件 + /// + /// + public override void OnOrderCancelled(Order order) + { + //lock(this) + { + DualPosition.OrderCancelled(order); + + // 这个地方会影响做市商的挂单功能 + //ResendOrder(order); + } + } + /// + /// 撤单被拒绝事件 + /// + /// + public override void OnOrderCancelReject(Order order) + { + // 撤单被拒绝,暂不操作 + } + + /// + /// 根据入场后的最高与最低价,跟踪止损 + /// + /// 当前价格 + /// 止损水平:为绝对值或百分比 + /// 止损类型:绝对值,Percent百分比 + /// 止损了返回止损前持仓,可用于后面的反手 + public virtual double TrailingStop(double currentPrice, double level, StopMode mode,string text) + { + //lock(this) + { + double qty = GetCurrentQty();//获取当前持仓 + double stop;//止损价 + //当前持仓 > 0 时 + if (qty > double.Epsilon) + { + //止损类型为百分比时 + if (StopMode.Percent == mode) + { + //止损价=入场后最高价*(1.0-止损百分比) + stop = HighestAfterEntry * (1.0 - level); + } + else//止损类型为绝对值 + { + //止损价=入场后最高价 - 止损绝对值 + stop = HighestAfterEntry - level; + } + //当前价格 < 止损价 时清仓 + if (currentPrice < stop) + { + TargetPosition = 0;//目标仓位=0,表示清仓 + TextParameter.Text = string.Format("跟踪止损 - 最高{0},止损{1}>当前{2}|{3}", + HighestAfterEntry, stop, currentPrice, + text); + return qty;//返回止损仓位,可用于后面的反手 + } + } + //当前持仓 < 0 时 + else if (qty < -double.Epsilon) + { + //止损类型为百分比时 + if (StopMode.Percent == mode) + { + stop = LowestAfterEntry * (1.0 + level); + } + else//止损类型为绝对值 + { + stop = LowestAfterEntry + level; + } + + if (currentPrice > stop) + { + TargetPosition = 0; + TextParameter.Text = string.Format("跟踪止损 - 最低{0},止损{1}<当前{2}|{3}", + HighestAfterEntry, stop, currentPrice, + text); + return qty; + } + } + + return 0; + } + } + + /// + /// 从入场均价开始算起,固定点位止损 + /// + /// 当前价 + /// 止损水平 + /// 止损类型 + /// 止损了返止损前持仓,可用于后面的反手 + public virtual double FixedStop(double currentPrice, double level, StopMode mode, string text) + { + //lock(this) + { + double qty = GetCurrentQty();//获取当前仓位 + double stop;//止损价 + //仓位>0时 + if (qty > double.Epsilon) + { + //止损类型为百分比时 + if (StopMode.Percent == mode) + { + stop = GetLongAvgPrice() * (1.0 - level); + } + else//止损类型为绝对值时 + { + stop = GetLongAvgPrice() - level; + } + if (currentPrice < stop) + { + TargetPosition = 0;//清仓 + TextParameter.Text = string.Format("固定止损 - 多头均价{0},止损{1}>当前{2}|{3}", + GetLongAvgPrice(), stop, currentPrice, + text); + return qty; + } + } + //仓位<0时 + else if (qty < -double.Epsilon) + { + if (StopMode.Percent == mode) + { + stop = GetShortAvgPrice() * (1.0 + level); + } + else + { + stop = GetShortAvgPrice() + level; + } + + if (currentPrice > stop) + { + TargetPosition = 0; + TextParameter.Text = string.Format("固定止损 - 空头均价{0},止损{1}<当前{2}|{3}", + GetShortAvgPrice(), stop, currentPrice, + text); + return qty; + } + } + return 0; + } + } + /// + /// 固定止赢 + /// + /// 当前价格 + /// + /// 获利停止类型:Absolute绝对,Percent百分比 + /// + /// + public virtual double TakeProfit(double currentPrice, double level, StopMode mode, string text) + { + //lock(this) + { + double qty = GetCurrentQty(); + double stop; + if (qty > double.Epsilon) + { + if (StopMode.Percent == mode) + { + stop = GetLongAvgPrice() * (1.0 + level); + } + else + { + stop = GetLongAvgPrice() + level; + } + if (currentPrice > stop) + { + TargetPosition = 0; + TextParameter.Text = string.Format("固定止赢 - 多头均价{0},止赢{1}<当前{2}|{3}", + GetLongAvgPrice(), stop, currentPrice, + text); + return qty; + } + } + else if (qty < -double.Epsilon) + { + if (StopMode.Percent == mode) + { + stop = GetShortAvgPrice() * (1.0 - level); + } + else + { + stop = GetShortAvgPrice() - level; + } + + if (currentPrice < stop) + { + TargetPosition = 0; + TextParameter.Text = string.Format("固定止赢 - 空头均价{0},止赢{1}>当前{2}|{3}", + GetShortAvgPrice(), stop, currentPrice, + text); + return qty; + } + } + return 0; + } + } + + /// + /// 尾盘清仓 + /// + /// 返回上次持仓量 + public virtual double ExitOnClose(double seconds,string text) + { + //lock(this) + { + double qty = GetCurrentQty(); + if (TimeHelper.GetTime(Clock.Now.AddSeconds(seconds)) >= TimeHelper.EndOfDay) + { + TargetPosition = 0; + TextParameter.Text = string.Format("尾盘,清仓|{0}", text); + return qty; + } + return 0; + } + } + /// + /// 换日,用户自己要记得挂单要撤 + /// + public virtual void ChangeTradingDay() + { + if (TimeHelper.BeginOfDay > TimeHelper.EndOfDay) + { + // 夜盘 + if (TimeHelper.GetTime(Clock.Now) > TimeHelper.EndOfDay + && TimeHelper.GetTime(Clock.Now) < TimeHelper.BeginOfDay) + { + DualPosition.ChangeTradingDay(); + } + } + else + { + if (TimeHelper.GetTime(Clock.Now) > TimeHelper.EndOfDay + || TimeHelper.GetTime(Clock.Now) < TimeHelper.BeginOfDay) + { + DualPosition.ChangeTradingDay(); + } + } + } + } + +} diff --git a/Demo/QuantBox.OQ.Demo/Msic/QQMsg2_code.cs b/Demo/QuantBox.OQ.Demo/Msic/QQMsg2_code.cs index b59db26..4cab133 100644 --- a/Demo/QuantBox.OQ.Demo/Msic/QQMsg2_code.cs +++ b/Demo/QuantBox.OQ.Demo/Msic/QQMsg2_code.cs @@ -1,71 +1,71 @@ -using System; - -using OpenQuant.API; -using System.Windows.Forms; -using System.Runtime.InteropServices; -using System.Threading; - -namespace QuantBox.OQ.Demo.Msic -{ - public class QQMsg2_code : Strategy - { - public const int WM_PASTE = 0x302; - public const int WM_KEYDOWN = 0x0100; - public const int WM_KEYUP = 0x0101; - - [DllImport("User32.dll", EntryPoint = "FindWindow")] - private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); - - [DllImport("User32.dll", EntryPoint = "PostMessage")] - public static extern int PostMessage( - IntPtr hWnd, // 信息发往的窗口的句柄 - int Msg, // 消息ID - int wParam, // 参数1 - int lParam // 参数2 - ); - - private string GroupName = "OpenQuant"; - private string textToCopy; - private IntPtr QQHwndSend = new IntPtr(0); - - public override void OnStrategyStart() - { - Send("测试剪切板,自动发消息"); - } - - private void SetClipboardTextAndSend() - { - try - { - Clipboard.SetText(textToCopy + "——消息发自OpenQuant"); - - // 粘贴 - PostMessage(QQHwndSend, WM_PASTE, 0, 0); - // 按下回车,修改QQ为只按回车就可以发送 - PostMessage(QQHwndSend, WM_KEYDOWN, 13, 0); - PostMessage(QQHwndSend, WM_KEYUP, 13, 0); - } - catch (Exception e) - { - Console.WriteLine(e); - } - } - - private void Send(string msg) - { - QQHwndSend = FindWindow("TXGuiFoundation", GroupName); - if (QQHwndSend.Equals(IntPtr.Zero)) - { - return; - } - // 此句会报错,所以改用另一线程实现 - //Clipboard.SetDataObject("测试剪切板,自动发消息。", true); - - textToCopy = msg; - - Thread runThread = new Thread(new ThreadStart(SetClipboardTextAndSend)); - runThread.SetApartmentState(ApartmentState.STA); - runThread.Start(); - } - } +using System; + +using OpenQuant.API; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Threading; + +namespace QuantBox.OQ.Demo.Msic +{ + public class QQMsg2_code : Strategy + { + public const int WM_PASTE = 0x302; + public const int WM_KEYDOWN = 0x0100; + public const int WM_KEYUP = 0x0101; + + [DllImport("User32.dll", EntryPoint = "FindWindow")] + private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("User32.dll", EntryPoint = "PostMessage")] + public static extern int PostMessage( + IntPtr hWnd, // 信息发往的窗口的句柄 + int Msg, // 消息ID + int wParam, // 参数1 + int lParam // 参数2 + ); + + private string GroupName = "OpenQuant"; + private string textToCopy; + private IntPtr QQHwndSend = new IntPtr(0); + + public override void OnStrategyStart() + { + Send("测试剪切板,自动发消息"); + } + + private void SetClipboardTextAndSend() + { + try + { + Clipboard.SetText(textToCopy + "——消息发自OpenQuant"); + + // 粘贴 + PostMessage(QQHwndSend, WM_PASTE, 0, 0); + // 按下回车,修改QQ为只按回车就可以发送 + PostMessage(QQHwndSend, WM_KEYDOWN, 13, 0); + PostMessage(QQHwndSend, WM_KEYUP, 13, 0); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + private void Send(string msg) + { + QQHwndSend = FindWindow("TXGuiFoundation", GroupName); + if (QQHwndSend.Equals(IntPtr.Zero)) + { + return; + } + // 此句会报错,所以改用另一线程实现 + //Clipboard.SetDataObject("测试剪切板,自动发消息。", true); + + textToCopy = msg; + + Thread runThread = new Thread(new ThreadStart(SetClipboardTextAndSend)); + runThread.SetApartmentState(ApartmentState.STA); + runThread.Start(); + } + } } \ No newline at end of file diff --git a/Demo/QuantBox.OQ.Demo/Optimization/Matlab2_Scenario.cs b/Demo/QuantBox.OQ.Demo/Optimization/Matlab2_Scenario.cs index 2a6822d..1bf376f 100644 --- a/Demo/QuantBox.OQ.Demo/Optimization/Matlab2_Scenario.cs +++ b/Demo/QuantBox.OQ.Demo/Optimization/Matlab2_Scenario.cs @@ -1,123 +1,123 @@ -using System; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Engine; -using System.Threading; -using System.IO; - -namespace QuantBox.OQ.Demo.Optimization -{ - /// - /// 使用内置的Simple Moving Average Crossover进行演示 - /// - /// 这个示例的主要目的是为了演示策略与Matlab的互动 - /// - /// 参考http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=111 - /// 要参加Interop.MLApp引用 - /// - public class Matlab2_Scenario : Scenario - {/* - FileSystemWatcher watcher; - - private AutoResetEvent _autoResetEvent = new AutoResetEvent(false); - - private void WatcherStrat(string path, string filter) - { - watcher = new FileSystemWatcher(); - watcher.Path = path; - watcher.Filter = filter; - - watcher.Created += new FileSystemEventHandler(OnProcess); - - watcher.EnableRaisingEvents = true; - } - - private void WatcherStop() - { - watcher.Created -= new FileSystemEventHandler(OnProcess); - - watcher.EnableRaisingEvents = false; - } - - private void OnProcess(object source, FileSystemEventArgs e) - { - if (e.ChangeType == WatcherChangeTypes.Created) - { - Console.WriteLine("{0},{1}", e.ChangeType, e.FullPath); - // 运行回测 - Start(); - // 解除等待 - _autoResetEvent.Set(); - } - } - - - public override void Run() - { - MLApp.MLAppClass matlab = new MLApp.MLAppClass(); - matlab.Visible = 1; //会显示Command Window - - matlab.Execute("clc; clear all; close all;"); - WatcherStrat(@"D:\test", "*.*"); - - Project project = Solution.Projects[0]; - - //int line = 0; - - for (int length1 = 3; length1 <= 7; length1++) - { - for (int length2 = 3; length2 <= 7; length2++) - { - if (length2 > length1) - { - // set new parameters - project.Parameters["Length1"].Value = length1; - project.Parameters["Length2"].Value = length2; - - // print parameters - Console.Write("Length1 = " + length1 + " Length2 = " + length2); - - // start backtest - // 这句话要写到matlab中的函数中去 - matlab.Execute(@"save D:\test\" + Clock.Now.Ticks); - // 等待策略跑完一次 - _autoResetEvent.WaitOne(); - - // calculate objective function - double objective = Solution.Portfolio.GetValue(); - // print objective - - Console.WriteLine(" Objective = " + objective); - // check best objective - } - } - } - - // 执行完后暂时不退出 - //matlab.Quit(); - //matlab = null; - - WatcherStop(); - } - */} -} - -/* - -% 从OpenQuant优化过后的结果导出成Excel,然后画参数与绩效的二维图,以下是两个参数的示例 -clc; clear all; close all; -A=xlsread('模拟退火算法.xlsx','Optimization_History'); -x=A(:,3);y=A(:,4);z=A(:,2); -t1=linspace(min(x),max(x),max(x)-min(x)); % 如果数据不多,最后的max(x)-min(x)+1可以改成50等 -t2=linspace(min(y),max(y),max(y)-min(y)); % 同上 -[X,Y]=meshgrid(t1,t2); -Z=griddata(x,y,z,X,Y,'v4'); -figure,surfc(X,Y,Z),colorbar -xlabel('x');grid on; -ylabel('y');grid on; -zlabel('z');grid on; -title('Performance'); - - +using System; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Engine; +using System.Threading; +using System.IO; + +namespace QuantBox.OQ.Demo.Optimization +{ + /// + /// 使用内置的Simple Moving Average Crossover进行演示 + /// + /// 这个示例的主要目的是为了演示策略与Matlab的互动 + /// + /// 参考http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=111 + /// 要参加Interop.MLApp引用 + /// + public class Matlab2_Scenario : Scenario + {/* + FileSystemWatcher watcher; + + private AutoResetEvent _autoResetEvent = new AutoResetEvent(false); + + private void WatcherStrat(string path, string filter) + { + watcher = new FileSystemWatcher(); + watcher.Path = path; + watcher.Filter = filter; + + watcher.Created += new FileSystemEventHandler(OnProcess); + + watcher.EnableRaisingEvents = true; + } + + private void WatcherStop() + { + watcher.Created -= new FileSystemEventHandler(OnProcess); + + watcher.EnableRaisingEvents = false; + } + + private void OnProcess(object source, FileSystemEventArgs e) + { + if (e.ChangeType == WatcherChangeTypes.Created) + { + Console.WriteLine("{0},{1}", e.ChangeType, e.FullPath); + // 运行回测 + Start(); + // 解除等待 + _autoResetEvent.Set(); + } + } + + + public override void Run() + { + MLApp.MLAppClass matlab = new MLApp.MLAppClass(); + matlab.Visible = 1; //会显示Command Window + + matlab.Execute("clc; clear all; close all;"); + WatcherStrat(@"D:\test", "*.*"); + + Project project = Solution.Projects[0]; + + //int line = 0; + + for (int length1 = 3; length1 <= 7; length1++) + { + for (int length2 = 3; length2 <= 7; length2++) + { + if (length2 > length1) + { + // set new parameters + project.Parameters["Length1"].Value = length1; + project.Parameters["Length2"].Value = length2; + + // print parameters + Console.Write("Length1 = " + length1 + " Length2 = " + length2); + + // start backtest + // 这句话要写到matlab中的函数中去 + matlab.Execute(@"save D:\test\" + Clock.Now.Ticks); + // 等待策略跑完一次 + _autoResetEvent.WaitOne(); + + // calculate objective function + double objective = Solution.Portfolio.GetValue(); + // print objective + + Console.WriteLine(" Objective = " + objective); + // check best objective + } + } + } + + // 执行完后暂时不退出 + //matlab.Quit(); + //matlab = null; + + WatcherStop(); + } + */} +} + +/* + +% 从OpenQuant优化过后的结果导出成Excel,然后画参数与绩效的二维图,以下是两个参数的示例 +clc; clear all; close all; +A=xlsread('模拟退火算法.xlsx','Optimization_History'); +x=A(:,3);y=A(:,4);z=A(:,2); +t1=linspace(min(x),max(x),max(x)-min(x)); % 如果数据不多,最后的max(x)-min(x)+1可以改成50等 +t2=linspace(min(y),max(y),max(y)-min(y)); % 同上 +[X,Y]=meshgrid(t1,t2); +Z=griddata(x,y,z,X,Y,'v4'); +figure,surfc(X,Y,Z),colorbar +xlabel('x');grid on; +ylabel('y');grid on; +zlabel('z');grid on; +title('Performance'); + + */ \ No newline at end of file diff --git a/Demo/QuantBox.OQ.Demo/Optimization/Matlab_Scenario.cs b/Demo/QuantBox.OQ.Demo/Optimization/Matlab_Scenario.cs index f9c8462..708a566 100644 --- a/Demo/QuantBox.OQ.Demo/Optimization/Matlab_Scenario.cs +++ b/Demo/QuantBox.OQ.Demo/Optimization/Matlab_Scenario.cs @@ -1,92 +1,92 @@ -using System; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Engine; - -namespace QuantBox.OQ.Demo.Optimization -{ - /// - /// 使用内置的Simple Moving Average Crossover进行演示 - /// - /// 使用Matlab进行3D绩效绘图 - /// - /// 参考http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=111 - /// 要参加Interop.MLApp引用 - /// - public class Matlab_Scenario : Scenario - {/* - public override void Run() - { - MLApp.MLAppClass matlab = new MLApp.MLAppClass(); - matlab.Visible = 1; //会显示Command Window - - matlab.Execute("clc; clear all; close all;"); - - Project project = Solution.Projects[0]; - - int line = 0; - - for (int length1 = 3; length1 <= 7; length1++) - { - for (int length2 = 3; length2 <= 7; length2++) - { - if (length2 > length1) - { - // set new parameters - project.Parameters["Length1"].Value = length1; - project.Parameters["Length2"].Value = length2; - - // print parameters - Console.Write("Length1 = " + length1 + " Length2 = " + length2); - - // start backtest - Start(); - - // calculate objective function - double objective = Solution.Portfolio.GetValue(); - // print objective - - Console.WriteLine(" Objective = " + objective); - // check best objective - - matlab.Execute(string.Format("x({0})={1}; y({0})={2}; z({0})={3};", ++line, length1, length2, objective)); - } - } - } - - matlab.Execute("t1=linspace(min(x),max(x),max(x)-min(x)+1); %% 如果数据不多,最后的max(x)-min(x)+1可以改成50等"); - matlab.Execute("t2=linspace(min(y),max(y),max(y)-min(y)+1); %% 同上"); - matlab.Execute("[X,Y]=meshgrid(t1,t2);"); - matlab.Execute("Z=griddata(x,y,z,X,Y,'v4');"); - matlab.Execute("figure,surfc(X,Y,Z),colorbar"); - matlab.Execute("xlabel('x'); ylabel('y'); zlabel('z');"); - matlab.Execute("title('Performance');"); - - matlab.Execute("save"); //保存一下,用于后期分析 - - // 执行完后暂时不退出 - //matlab.Quit(); - //matlab = null; - } - */} -} - -/* - -% 从OpenQuant优化过后的结果导出成Excel,然后画参数与绩效的二维图,以下是两个参数的示例 -clc; clear all; close all; -A=xlsread('模拟退火算法.xlsx','Optimization_History'); -x=A(:,3);y=A(:,4);z=A(:,2); -t1=linspace(min(x),max(x),max(x)-min(x)); % 如果数据不多,最后的max(x)-min(x)+1可以改成50等 -t2=linspace(min(y),max(y),max(y)-min(y)); % 同上 -[X,Y]=meshgrid(t1,t2); -Z=griddata(x,y,z,X,Y,'v4'); -figure,surfc(X,Y,Z),colorbar -xlabel('x');grid on; -ylabel('y');grid on; -zlabel('z');grid on; -title('Performance'); - - +using System; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Engine; + +namespace QuantBox.OQ.Demo.Optimization +{ + /// + /// 使用内置的Simple Moving Average Crossover进行演示 + /// + /// 使用Matlab进行3D绩效绘图 + /// + /// 参考http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=111 + /// 要参加Interop.MLApp引用 + /// + public class Matlab_Scenario : Scenario + {/* + public override void Run() + { + MLApp.MLAppClass matlab = new MLApp.MLAppClass(); + matlab.Visible = 1; //会显示Command Window + + matlab.Execute("clc; clear all; close all;"); + + Project project = Solution.Projects[0]; + + int line = 0; + + for (int length1 = 3; length1 <= 7; length1++) + { + for (int length2 = 3; length2 <= 7; length2++) + { + if (length2 > length1) + { + // set new parameters + project.Parameters["Length1"].Value = length1; + project.Parameters["Length2"].Value = length2; + + // print parameters + Console.Write("Length1 = " + length1 + " Length2 = " + length2); + + // start backtest + Start(); + + // calculate objective function + double objective = Solution.Portfolio.GetValue(); + // print objective + + Console.WriteLine(" Objective = " + objective); + // check best objective + + matlab.Execute(string.Format("x({0})={1}; y({0})={2}; z({0})={3};", ++line, length1, length2, objective)); + } + } + } + + matlab.Execute("t1=linspace(min(x),max(x),max(x)-min(x)+1); %% 如果数据不多,最后的max(x)-min(x)+1可以改成50等"); + matlab.Execute("t2=linspace(min(y),max(y),max(y)-min(y)+1); %% 同上"); + matlab.Execute("[X,Y]=meshgrid(t1,t2);"); + matlab.Execute("Z=griddata(x,y,z,X,Y,'v4');"); + matlab.Execute("figure,surfc(X,Y,Z),colorbar"); + matlab.Execute("xlabel('x'); ylabel('y'); zlabel('z');"); + matlab.Execute("title('Performance');"); + + matlab.Execute("save"); //保存一下,用于后期分析 + + // 执行完后暂时不退出 + //matlab.Quit(); + //matlab = null; + } + */} +} + +/* + +% 从OpenQuant优化过后的结果导出成Excel,然后画参数与绩效的二维图,以下是两个参数的示例 +clc; clear all; close all; +A=xlsread('模拟退火算法.xlsx','Optimization_History'); +x=A(:,3);y=A(:,4);z=A(:,2); +t1=linspace(min(x),max(x),max(x)-min(x)); % 如果数据不多,最后的max(x)-min(x)+1可以改成50等 +t2=linspace(min(y),max(y),max(y)-min(y)); % 同上 +[X,Y]=meshgrid(t1,t2); +Z=griddata(x,y,z,X,Y,'v4'); +figure,surfc(X,Y,Z),colorbar +xlabel('x');grid on; +ylabel('y');grid on; +zlabel('z');grid on; +title('Performance'); + + */ \ No newline at end of file diff --git a/Demo/QuantBox.OQ.Demo/Optimization/SharpeRatio_Scenario.cs b/Demo/QuantBox.OQ.Demo/Optimization/SharpeRatio_Scenario.cs index fef0c2d..a2bde67 100644 --- a/Demo/QuantBox.OQ.Demo/Optimization/SharpeRatio_Scenario.cs +++ b/Demo/QuantBox.OQ.Demo/Optimization/SharpeRatio_Scenario.cs @@ -1,80 +1,80 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Engine; - -namespace QuantBox.OQ.Demo.Optimization -{ - /// - /// 计算率夏普比率 - /// - public class SharpeRatio_Scenario : Scenario - { - public override void Run() - { - Start(); - - //年无风险利率 - double riskFreeRate = 0.03; - double SR = SharpeRatio(riskFreeRate); - Console.WriteLine(SR); - } - - public double SharpeRatio(double RiskFreeRate) - { - int Days = Solution.Performance.PnLSeries.Count; - TimeSeries ReturnSeries = new TimeSeries(); - double Portfolio0 = Solution.Cash; - double Portfolio1; - for (int t = 0; t < Days; ++t) - { - DateTime date = Solution.Performance.PnLSeries.GetDateTime(t); - Portfolio1 = Solution.Performance.PnLSeries[t] + Portfolio0; - double DailyReturn = Portfolio1 / Portfolio0 - 1; - Portfolio0 = Portfolio1; - ReturnSeries.Add(date, DailyReturn); - } - - double Mean = ReturnSeries.GetMean(0, Days - 1); - double Std = ReturnSeries.GetStdDev(0, Days - 1); - - //年化收益均值、波动率 - Mean = Mean * 250; - Std = Std * Math.Sqrt(250); - - double SR = (Mean - RiskFreeRate) / Std; - return SR; - } - } -} - -/* -夏普比率公式: -Sharpe Ratio = (Mean Return - Risk Free Rate)/Volatility -Mean Return是收益率的均值 -Volatility是收益率的标准差 -Risk Free Rate是无风险利率 - -使用方法 -1). -Tools->Options->Memory Management -将Enable built-in porfolio performance和Enable interval performance update选上, -然后将Interval length改成86400 - -2) -代码 -先得出日收益率序列ReturnSeries,然后求收益率序列的均值、标准差 - - -资产组合或者说策略的收益率可以有两种,一是对数收益率,二是简单收益率 -对数收益率 = log( Price(t) / Price(t-1) ) = log(Price(t)) - log(Price(t-1)) -简单收益率 = Price(t) / Price(t-1) - 1 -数学计算时常用对数收益率,因为对数收益率有两个非常好的特性: -1)一年的日对数收益率之和刚好是年对数收益率,而普通收益率就没有这个特性 -2)此外对数收益率的好处就是涨跌10%对应在价格上是一样的,用简单收益率的话,100元的股票,跌10%变成了90元,再涨10%只能是99元,而不是100元,相反对数收益率就不存在这个问题。 - -所以很多时候用对数收益率好一些,但是这里其实结果差别不大就后来又用了普通收益率 - */ +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Engine; + +namespace QuantBox.OQ.Demo.Optimization +{ + /// + /// 计算率夏普比率 + /// + public class SharpeRatio_Scenario : Scenario + { + public override void Run() + { + Start(); + + //年无风险利率 + double riskFreeRate = 0.03; + double SR = SharpeRatio(riskFreeRate); + Console.WriteLine(SR); + } + + public double SharpeRatio(double RiskFreeRate) + { + int Days = Solution.Performance.PnLSeries.Count; + TimeSeries ReturnSeries = new TimeSeries(); + double Portfolio0 = Solution.Cash; + double Portfolio1; + for (int t = 0; t < Days; ++t) + { + DateTime date = Solution.Performance.PnLSeries.GetDateTime(t); + Portfolio1 = Solution.Performance.PnLSeries[t] + Portfolio0; + double DailyReturn = Portfolio1 / Portfolio0 - 1; + Portfolio0 = Portfolio1; + ReturnSeries.Add(date, DailyReturn); + } + + double Mean = ReturnSeries.GetMean(0, Days - 1); + double Std = ReturnSeries.GetStdDev(0, Days - 1); + + //年化收益均值、波动率 + Mean = Mean * 250; + Std = Std * Math.Sqrt(250); + + double SR = (Mean - RiskFreeRate) / Std; + return SR; + } + } +} + +/* +夏普比率公式: +Sharpe Ratio = (Mean Return - Risk Free Rate)/Volatility +Mean Return是收益率的均值 +Volatility是收益率的标准差 +Risk Free Rate是无风险利率 + +使用方法 +1). +Tools->Options->Memory Management +将Enable built-in porfolio performance和Enable interval performance update选上, +然后将Interval length改成86400 + +2) +代码 +先得出日收益率序列ReturnSeries,然后求收益率序列的均值、标准差 + + +资产组合或者说策略的收益率可以有两种,一是对数收益率,二是简单收益率 +对数收益率 = log( Price(t) / Price(t-1) ) = log(Price(t)) - log(Price(t-1)) +简单收益率 = Price(t) / Price(t-1) - 1 +数学计算时常用对数收益率,因为对数收益率有两个非常好的特性: +1)一年的日对数收益率之和刚好是年对数收益率,而普通收益率就没有这个特性 +2)此外对数收益率的好处就是涨跌10%对应在价格上是一样的,用简单收益率的话,100元的股票,跌10%变成了90元,再涨10%只能是99元,而不是100元,相反对数收益率就不存在这个问题。 + +所以很多时候用对数收益率好一些,但是这里其实结果差别不大就后来又用了普通收益率 + */ diff --git a/Demo/QuantBox.OQ.Demo/Plugins_Functions/CTP_code.cs b/Demo/QuantBox.OQ.Demo/Plugins_Functions/CTP_code.cs index 2d4f16f..7bdffc0 100644 --- a/Demo/QuantBox.OQ.Demo/Plugins_Functions/CTP_code.cs +++ b/Demo/QuantBox.OQ.Demo/Plugins_Functions/CTP_code.cs @@ -1,135 +1,135 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; - -using QuantBox.Helper.CTP; -using QuantBox.CSharp2CTP; - -namespace QuantBox.OQ.Demo.Plugins_Functions -{ - /// - /// 取合约、行情、保证金率与手续费 - /// 订阅深度行情、交易所状态 - /// - /// OnRspQryDepthMarketData:查一次,返回一次。通过交易接口。没有订阅的可以返回 - /// OnRtnDepthMarketData:是总是返回。通过行情接口。只能返回订阅过的。 - /// 这个事件在最后触发,优先级循序为:Trade\Quote\MarketDepth\OnRtnDepthMarketData - /// - /// 要使用OnRtnDepthMarketData,请将插件属性中的EmitOnRtnDepthMarketData改成True - /// - public class CTP_code:Strategy - { - public override void OnStrategyStart() - { - CTPAPI.GetInstance().OnRspQryInstrument += new CTPAPI.RspQryInstrument(OnRspQryInstrument); - CTPAPI.GetInstance().OnRspQryInstrumentMarginRate += new CTPAPI.RspQryInstrumentMarginRate(OnRspQryInstrumentMarginRate); - CTPAPI.GetInstance().OnRspQryInstrumentCommissionRate += new CTPAPI.RspQryInstrumentCommissionRate(OnRspQryInstrumentCommissionRate); - // 交易所状态 - CTPAPI.GetInstance().OnRtnInstrumentStatus += new CTPAPI.RtnInstrumentStatus(OnRtnInstrumentStatus); - - CTPAPI.GetInstance().OnRspQryTradingAccount += new CTPAPI.RspQryTradingAccount(OnRspQryTradingAccount); - - CTPAPI.GetInstance().OnRspReqQryInvestorPosition += new CTPAPI.RspReqQryInvestorPosition(OnRspReqQryInvestorPosition); - - // 此方法已经过期,在插件3.8.2.0中开始废弃 - //CTPAPI.GetInstance().OnRtnDepthMarketData += new CTPAPI.RtnDepthMarketData(OnRtnDepthMarketData); - } - - void OnRspReqQryInvestorPosition(CThostFtdcInvestorPositionField pInvestorPosition) - { - Console.WriteLine("==持仓"); - Console.WriteLine(pInvestorPosition.InstrumentID); - } - - void OnRspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount) - { - Console.WriteLine("==资金"); - Console.WriteLine(pTradingAccount.Balance); - Console.WriteLine(pTradingAccount.TradingDay); - } - - public override void OnStrategyStop() - { - CTPAPI.GetInstance().OnRspQryInstrument -= new CTPAPI.RspQryInstrument(OnRspQryInstrument); - CTPAPI.GetInstance().OnRspQryInstrumentMarginRate -= new CTPAPI.RspQryInstrumentMarginRate(OnRspQryInstrumentMarginRate); - CTPAPI.GetInstance().OnRspQryInstrumentCommissionRate -= new CTPAPI.RspQryInstrumentCommissionRate(OnRspQryInstrumentCommissionRate); - - CTPAPI.GetInstance().OnRtnInstrumentStatus -= new CTPAPI.RtnInstrumentStatus(OnRtnInstrumentStatus); - - CTPAPI.GetInstance().OnRspQryTradingAccount -= new CTPAPI.RspQryTradingAccount(OnRspQryTradingAccount); - - // 此方法已经过期,在插件3.8.2.0中开始废弃 - //CTPAPI.GetInstance().OnRtnDepthMarketData -= new CTPAPI.RtnDepthMarketData(OnRtnDepthMarketData); - } - - public override void OnBar(Bar bar) - { - //以下四句只是演示,实盘中请保存查询出来的结果,并且一天只查一次 - CTPAPI.GetInstance().ReqQryInstrument("IF1312"); - - // 一定得加上TThostFtdcHedgeFlagType - CTPAPI.GetInstance().ReqQryInstrumentMarginRate("IF1312", TThostFtdcHedgeFlagType.Speculation); - - //目前模拟平台目前查询没有返回,实盘时返回的是产品的手续费,如查"IF1312",返回的是"IF" - CTPAPI.GetInstance().ReqQryInstrumentCommissionRate("IF1312"); - - //通过交易接口查询,主要用来取涨跌停或没有直接订阅的行情 - CTPAPI.GetInstance().ReqQryDepthMarketData("IF1309"); - } - - void OnRspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateField pInstrumentMarginRate) - { - Console.WriteLine("==保证金率"); - Console.WriteLine(pInstrumentMarginRate.InstrumentID); - Console.WriteLine(pInstrumentMarginRate.LongMarginRatioByMoney); - Console.WriteLine(pInstrumentMarginRate.LongMarginRatioByVolume); - Console.WriteLine(pInstrumentMarginRate.ShortMarginRatioByMoney); - Console.WriteLine(pInstrumentMarginRate.ShortMarginRatioByVolume); - } - - void OnRspQryInstrument(CThostFtdcInstrumentField pInstrument) - { - Console.WriteLine("==合约列表"); - Console.WriteLine(pInstrument.LongMarginRatio); - Console.WriteLine(pInstrument.ShortMarginRatio); - } - - void OnRspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateField pInstrumentCommissionRate) - { - Console.WriteLine("==手续费率"); - Console.WriteLine(pInstrumentCommissionRate.CloseRatioByMoney); - Console.WriteLine(pInstrumentCommissionRate.CloseRatioByVolume); - } - - void OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField pInstrumentStatus) - { - // 由于只在有新消息过来时才会收到,所以可能认为不好测试,看不出效果 - // 在测试时,把插件属性的ResumeType改成THOST_TERT_RESTART,然后连接CTP就可以看到效果了。 - Console.WriteLine("==交易所状态"); - Console.WriteLine("{0},{1},{2}", - pInstrumentStatus.ExchangeID, pInstrumentStatus.InstrumentID, - pInstrumentStatus.InstrumentStatus); - } - - //void OnRspQryDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData) - //{ - // Console.WriteLine("==取深度行情"); - // Console.WriteLine(pDepthMarketData.InstrumentID); - // Console.WriteLine(pDepthMarketData.LastPrice); - // Console.WriteLine(pDepthMarketData.UpperLimitPrice); - // Console.WriteLine(pDepthMarketData.LowerLimitPrice); - //} - - void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData) - { - // 得打开EmitOnRtnDepthMarketData开关 - Console.WriteLine("++订阅深度行情"); - Console.WriteLine(pDepthMarketData.InstrumentID); - Console.WriteLine(pDepthMarketData.LastPrice); - Console.WriteLine(pDepthMarketData.OpenInterest); - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; + +using QuantBox.Helper.CTP; +using QuantBox.CSharp2CTP; + +namespace QuantBox.OQ.Demo.Plugins_Functions +{ + /// + /// 取合约、行情、保证金率与手续费 + /// 订阅深度行情、交易所状态 + /// + /// OnRspQryDepthMarketData:查一次,返回一次。通过交易接口。没有订阅的可以返回 + /// OnRtnDepthMarketData:是总是返回。通过行情接口。只能返回订阅过的。 + /// 这个事件在最后触发,优先级循序为:Trade\Quote\MarketDepth\OnRtnDepthMarketData + /// + /// 要使用OnRtnDepthMarketData,请将插件属性中的EmitOnRtnDepthMarketData改成True + /// + public class CTP_code:Strategy + { + public override void OnStrategyStart() + { + CTPAPI.GetInstance().OnRspQryInstrument += new CTPAPI.RspQryInstrument(OnRspQryInstrument); + CTPAPI.GetInstance().OnRspQryInstrumentMarginRate += new CTPAPI.RspQryInstrumentMarginRate(OnRspQryInstrumentMarginRate); + CTPAPI.GetInstance().OnRspQryInstrumentCommissionRate += new CTPAPI.RspQryInstrumentCommissionRate(OnRspQryInstrumentCommissionRate); + // 交易所状态 + CTPAPI.GetInstance().OnRtnInstrumentStatus += new CTPAPI.RtnInstrumentStatus(OnRtnInstrumentStatus); + + CTPAPI.GetInstance().OnRspQryTradingAccount += new CTPAPI.RspQryTradingAccount(OnRspQryTradingAccount); + + CTPAPI.GetInstance().OnRspReqQryInvestorPosition += new CTPAPI.RspReqQryInvestorPosition(OnRspReqQryInvestorPosition); + + // 此方法已经过期,在插件3.8.2.0中开始废弃 + //CTPAPI.GetInstance().OnRtnDepthMarketData += new CTPAPI.RtnDepthMarketData(OnRtnDepthMarketData); + } + + void OnRspReqQryInvestorPosition(CThostFtdcInvestorPositionField pInvestorPosition) + { + Console.WriteLine("==持仓"); + Console.WriteLine(pInvestorPosition.InstrumentID); + } + + void OnRspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount) + { + Console.WriteLine("==资金"); + Console.WriteLine(pTradingAccount.Balance); + Console.WriteLine(pTradingAccount.TradingDay); + } + + public override void OnStrategyStop() + { + CTPAPI.GetInstance().OnRspQryInstrument -= new CTPAPI.RspQryInstrument(OnRspQryInstrument); + CTPAPI.GetInstance().OnRspQryInstrumentMarginRate -= new CTPAPI.RspQryInstrumentMarginRate(OnRspQryInstrumentMarginRate); + CTPAPI.GetInstance().OnRspQryInstrumentCommissionRate -= new CTPAPI.RspQryInstrumentCommissionRate(OnRspQryInstrumentCommissionRate); + + CTPAPI.GetInstance().OnRtnInstrumentStatus -= new CTPAPI.RtnInstrumentStatus(OnRtnInstrumentStatus); + + CTPAPI.GetInstance().OnRspQryTradingAccount -= new CTPAPI.RspQryTradingAccount(OnRspQryTradingAccount); + + // 此方法已经过期,在插件3.8.2.0中开始废弃 + //CTPAPI.GetInstance().OnRtnDepthMarketData -= new CTPAPI.RtnDepthMarketData(OnRtnDepthMarketData); + } + + public override void OnBar(Bar bar) + { + //以下四句只是演示,实盘中请保存查询出来的结果,并且一天只查一次 + CTPAPI.GetInstance().ReqQryInstrument("IF1312"); + + // 一定得加上TThostFtdcHedgeFlagType + CTPAPI.GetInstance().ReqQryInstrumentMarginRate("IF1312", TThostFtdcHedgeFlagType.Speculation); + + //目前模拟平台目前查询没有返回,实盘时返回的是产品的手续费,如查"IF1312",返回的是"IF" + CTPAPI.GetInstance().ReqQryInstrumentCommissionRate("IF1312"); + + //通过交易接口查询,主要用来取涨跌停或没有直接订阅的行情 + CTPAPI.GetInstance().ReqQryDepthMarketData("IF1309"); + } + + void OnRspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateField pInstrumentMarginRate) + { + Console.WriteLine("==保证金率"); + Console.WriteLine(pInstrumentMarginRate.InstrumentID); + Console.WriteLine(pInstrumentMarginRate.LongMarginRatioByMoney); + Console.WriteLine(pInstrumentMarginRate.LongMarginRatioByVolume); + Console.WriteLine(pInstrumentMarginRate.ShortMarginRatioByMoney); + Console.WriteLine(pInstrumentMarginRate.ShortMarginRatioByVolume); + } + + void OnRspQryInstrument(CThostFtdcInstrumentField pInstrument) + { + Console.WriteLine("==合约列表"); + Console.WriteLine(pInstrument.LongMarginRatio); + Console.WriteLine(pInstrument.ShortMarginRatio); + } + + void OnRspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateField pInstrumentCommissionRate) + { + Console.WriteLine("==手续费率"); + Console.WriteLine(pInstrumentCommissionRate.CloseRatioByMoney); + Console.WriteLine(pInstrumentCommissionRate.CloseRatioByVolume); + } + + void OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField pInstrumentStatus) + { + // 由于只在有新消息过来时才会收到,所以可能认为不好测试,看不出效果 + // 在测试时,把插件属性的ResumeType改成THOST_TERT_RESTART,然后连接CTP就可以看到效果了。 + Console.WriteLine("==交易所状态"); + Console.WriteLine("{0},{1},{2}", + pInstrumentStatus.ExchangeID, pInstrumentStatus.InstrumentID, + pInstrumentStatus.InstrumentStatus); + } + + //void OnRspQryDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData) + //{ + // Console.WriteLine("==取深度行情"); + // Console.WriteLine(pDepthMarketData.InstrumentID); + // Console.WriteLine(pDepthMarketData.LastPrice); + // Console.WriteLine(pDepthMarketData.UpperLimitPrice); + // Console.WriteLine(pDepthMarketData.LowerLimitPrice); + //} + + void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData) + { + // 得打开EmitOnRtnDepthMarketData开关 + Console.WriteLine("++订阅深度行情"); + Console.WriteLine(pDepthMarketData.InstrumentID); + Console.WriteLine(pDepthMarketData.LastPrice); + Console.WriteLine(pDepthMarketData.OpenInterest); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/QuantBox.OQ.Demo.csproj b/Demo/QuantBox.OQ.Demo/QuantBox.OQ.Demo.csproj index 8ea490f..27265b1 100644 --- a/Demo/QuantBox.OQ.Demo/QuantBox.OQ.Demo.csproj +++ b/Demo/QuantBox.OQ.Demo/QuantBox.OQ.Demo.csproj @@ -20,6 +20,7 @@ DEBUG;TRACE prompt 4 + x86 pdbonly @@ -43,15 +44,15 @@ False - ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTP.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.CSharp2CTP.dll False - ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.Helper.CTP.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.Helper.CTP.dll - + False - ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Extensions.dll diff --git a/Demo/QuantBox.OQ.Demo/QuantBox.OQ.Demo.csproj.user b/Demo/QuantBox.OQ.Demo/QuantBox.OQ.Demo.csproj.user new file mode 100644 index 0000000..497396c --- /dev/null +++ b/Demo/QuantBox.OQ.Demo/QuantBox.OQ.Demo.csproj.user @@ -0,0 +1,10 @@ + + + + D:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\;D:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\ + + + Program + D:\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\OpenQuant.exe + + \ No newline at end of file diff --git a/Demo/QuantBox.OQ.Demo/Scenarios/PortfolioPersistent_code.cs b/Demo/QuantBox.OQ.Demo/Scenarios/PortfolioPersistent_code.cs index 9b8c140..1c12314 100644 --- a/Demo/QuantBox.OQ.Demo/Scenarios/PortfolioPersistent_code.cs +++ b/Demo/QuantBox.OQ.Demo/Scenarios/PortfolioPersistent_code.cs @@ -1,93 +1,93 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using System.Xml.Serialization; -using System.IO; - -namespace QuantBox.OQ.Demo.Scenarios -{ - public class PortfolioPersistent_code : Strategy - { - /// - /// 持仓组合持久化 - /// - /// 按 策略_合约.xml 进行保存,用户可以自己编辑此文件 - /// - public override void OnStrategyStart() - { - LoadPosition(); - } - - public override void OnStrategyStop() - { - SavePosition(); - } - - private void LoadPosition() - { - MyPosition pos = new MyPosition(); - XmlSerializer serializer = new XmlSerializer(pos.GetType()); - - string path = string.Format("{0}_{1}.xml", Name, Instrument); - - try - { - using (FileStream stream = new FileStream(path, FileMode.Open)) - { - pos = (MyPosition)serializer.Deserialize(stream); - stream.Close(); - - if (pos.Amount != 0) - { - Portfolio.Add(pos.EntryDate, pos.Amount > 0 ? TransactionSide.Buy : TransactionSide.Sell, - Math.Abs(pos.Amount), Instrument, pos.Price, "从XML中初始化"); - } - - Console.WriteLine(string.Format("加载路径:{0},持仓:{1},价格:{2}", path,pos.Amount,pos.Price)); - } - } - catch(Exception ex) - { - Console.WriteLine(ex); - } - } - - private void SavePosition() - { - MyPosition pos = new MyPosition(); - XmlSerializer serializer = new XmlSerializer(pos.GetType()); - - string path = string.Format("{0}_{1}.xml", Name, Instrument); - using (TextWriter writer = new StreamWriter(path)) - { - if (null == Position) - { - pos.EntryDate = Clock.Now; - pos.Amount = 0; - pos.Price = 0; - } - else - { - pos.EntryDate = Position.EntryDate; - pos.Amount = Position.Amount; - pos.Price = Position.GetPrice(); - } - - serializer.Serialize(writer, pos); - writer.Close(); - - Console.WriteLine(string.Format("保存路径:{0},持仓:{1},价格:{2}", path, pos.Amount, pos.Price)); - } - } - } -} - -public class MyPosition -{ - public DateTime EntryDate; - public double Amount; - public double Price; -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using System.Xml.Serialization; +using System.IO; + +namespace QuantBox.OQ.Demo.Scenarios +{ + public class PortfolioPersistent_code : Strategy + { + /// + /// 持仓组合持久化 + /// + /// 按 策略_合约.xml 进行保存,用户可以自己编辑此文件 + /// + public override void OnStrategyStart() + { + LoadPosition(); + } + + public override void OnStrategyStop() + { + SavePosition(); + } + + private void LoadPosition() + { + MyPosition pos = new MyPosition(); + XmlSerializer serializer = new XmlSerializer(pos.GetType()); + + string path = string.Format("{0}_{1}.xml", Name, Instrument); + + try + { + using (FileStream stream = new FileStream(path, FileMode.Open)) + { + pos = (MyPosition)serializer.Deserialize(stream); + stream.Close(); + + if (pos.Amount != 0) + { + Portfolio.Add(pos.EntryDate, pos.Amount > 0 ? TransactionSide.Buy : TransactionSide.Sell, + Math.Abs(pos.Amount), Instrument, pos.Price, "从XML中初始化"); + } + + Console.WriteLine(string.Format("加载路径:{0},持仓:{1},价格:{2}", path,pos.Amount,pos.Price)); + } + } + catch(Exception ex) + { + Console.WriteLine(ex); + } + } + + private void SavePosition() + { + MyPosition pos = new MyPosition(); + XmlSerializer serializer = new XmlSerializer(pos.GetType()); + + string path = string.Format("{0}_{1}.xml", Name, Instrument); + using (TextWriter writer = new StreamWriter(path)) + { + if (null == Position) + { + pos.EntryDate = Clock.Now; + pos.Amount = 0; + pos.Price = 0; + } + else + { + pos.EntryDate = Position.EntryDate; + pos.Amount = Position.Amount; + pos.Price = Position.GetPrice(); + } + + serializer.Serialize(writer, pos); + writer.Close(); + + Console.WriteLine(string.Format("保存路径:{0},持仓:{1},价格:{2}", path, pos.Amount, pos.Price)); + } + } + } +} + +public class MyPosition +{ + public DateTime EntryDate; + public double Amount; + public double Price; +} diff --git a/Demo/QuantBox.OQ.Demo/StopStrategy/Comfirm_code.cs b/Demo/QuantBox.OQ.Demo/StopStrategy/Comfirm_code.cs index 725eab2..4faee86 100644 --- a/Demo/QuantBox.OQ.Demo/StopStrategy/Comfirm_code.cs +++ b/Demo/QuantBox.OQ.Demo/StopStrategy/Comfirm_code.cs @@ -1,47 +1,47 @@ -using System; -using System.Drawing; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; - -namespace QuantBox.OQ.Demo.StopStrategy -{ - public class MyStrategy : Strategy - { - bool bStopStrategy = false; - public override void OnStrategyStart() - { - DialogResult dr = MessageBox.Show("是否停止?", "确认", MessageBoxButtons.OKCancel); - if (dr == DialogResult.OK) - { - //1.直接停止。其实写在这并不能停止策略 - //StopStrategy(); - - //2.使用定时器,3秒后停止 - AddTimer(Clock.Now.AddSeconds(3)); - - //3.使用变量,在策略运行的地方停止 - //bStopStrategy = true; - } - } - - public override void OnTimer(DateTime datetime, Object data) - { - Console.WriteLine("OnTimer"); - StopStrategy(); - } - - public override void OnBar(Bar bar) - { - if (bStopStrategy) - { - Console.WriteLine("OnBar"); - StopStrategy(); - } - - Console.WriteLine(bar); - } - - } +using System; +using System.Drawing; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; + +namespace QuantBox.OQ.Demo.StopStrategy +{ + public class MyStrategy : Strategy + { + bool bStopStrategy = false; + public override void OnStrategyStart() + { + DialogResult dr = MessageBox.Show("是否停止?", "确认", MessageBoxButtons.OKCancel); + if (dr == DialogResult.OK) + { + //1.直接停止。其实写在这并不能停止策略 + //StopStrategy(); + + //2.使用定时器,3秒后停止 + AddTimer(Clock.Now.AddSeconds(3)); + + //3.使用变量,在策略运行的地方停止 + //bStopStrategy = true; + } + } + + public override void OnTimer(DateTime datetime, Object data) + { + Console.WriteLine("OnTimer"); + StopStrategy(); + } + + public override void OnBar(Bar bar) + { + if (bStopStrategy) + { + Console.WriteLine("OnBar"); + StopStrategy(); + } + + Console.WriteLine(bar); + } + + } } \ No newline at end of file diff --git a/Demo/QuantBox.OQ.Demo/StopStrategy/Form_code.cs b/Demo/QuantBox.OQ.Demo/StopStrategy/Form_code.cs index e774779..27b0c7f 100644 --- a/Demo/QuantBox.OQ.Demo/StopStrategy/Form_code.cs +++ b/Demo/QuantBox.OQ.Demo/StopStrategy/Form_code.cs @@ -1,64 +1,64 @@ -using System; -using System.Drawing; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; - -namespace QuantBox.OQ.Demo.StopStrategy -{ - public class Form1 : Form - { - public bool bStopStrategy = false; - public Button button1; - public Form1() - { - button1 = new Button(); - button1.Size = new Size(40, 40); - button1.Location = new Point(30, 30); - button1.Text = "Click me"; - this.Controls.Add(button1); - button1.Click += new EventHandler(button1_Click); - } - private void button1_Click(object sender, EventArgs e) - { - MessageBox.Show("Hello World"); - bStopStrategy = true; - } - } - - /// - /// 弹出窗口,在窗口上点击按钮后停止 - /// - /// 或在User Commands中停止 - /// - public class Form_code:Strategy - { - private Form1 test; - - public override void OnStrategyStart() - { - test = new Form1(); - System.Threading.ThreadPool.QueueUserWorkItem(delegate(object state) - { - Application.Run(test); - }); - } - - public override void OnBar(Bar bar) - { - if (test.bStopStrategy) - { - Console.WriteLine("OnBar"); - StopStrategy(); - } - - Console.WriteLine(bar); - } - - public override void OnUserCommand(UserCommand command) - { - StopStrategy(); - } - } -} +using System; +using System.Drawing; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; + +namespace QuantBox.OQ.Demo.StopStrategy +{ + public class Form1 : Form + { + public bool bStopStrategy = false; + public Button button1; + public Form1() + { + button1 = new Button(); + button1.Size = new Size(40, 40); + button1.Location = new Point(30, 30); + button1.Text = "Click me"; + this.Controls.Add(button1); + button1.Click += new EventHandler(button1_Click); + } + private void button1_Click(object sender, EventArgs e) + { + MessageBox.Show("Hello World"); + bStopStrategy = true; + } + } + + /// + /// 弹出窗口,在窗口上点击按钮后停止 + /// + /// 或在User Commands中停止 + /// + public class Form_code:Strategy + { + private Form1 test; + + public override void OnStrategyStart() + { + test = new Form1(); + System.Threading.ThreadPool.QueueUserWorkItem(delegate(object state) + { + Application.Run(test); + }); + } + + public override void OnBar(Bar bar) + { + if (test.bStopStrategy) + { + Console.WriteLine("OnBar"); + StopStrategy(); + } + + Console.WriteLine(bar); + } + + public override void OnUserCommand(UserCommand command) + { + StopStrategy(); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/StopStrategy/LimitAccount_code.cs b/Demo/QuantBox.OQ.Demo/StopStrategy/LimitAccount_code.cs index 10ad0ee..d2cf553 100644 --- a/Demo/QuantBox.OQ.Demo/StopStrategy/LimitAccount_code.cs +++ b/Demo/QuantBox.OQ.Demo/StopStrategy/LimitAccount_code.cs @@ -1,35 +1,35 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -namespace QuantBox.OQ.Demo.StopStrategy -{ - /// - /// 限制指定账号使用 - /// - public class LimitAccount_code : Strategy - { - bool CheckAccount() - { - BrokerInfo bi = DataManager.GetBrokerInfo(); - return bi.Accounts[0].Name.CompareTo("你的账号") == 0; - } - - public override void OnPositionOpened() - { - if (!CheckAccount()) - StopStrategy(); - } - - public override void OnBar(Bar bar) - { - if (!CheckAccount()) - StopStrategy(); - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +namespace QuantBox.OQ.Demo.StopStrategy +{ + /// + /// 限制指定账号使用 + /// + public class LimitAccount_code : Strategy + { + bool CheckAccount() + { + BrokerInfo bi = DataManager.GetBrokerInfo(); + return bi.Accounts[0].Name.CompareTo("你的账号") == 0; + } + + public override void OnPositionOpened() + { + if (!CheckAccount()) + StopStrategy(); + } + + public override void OnBar(Bar bar) + { + if (!CheckAccount()) + StopStrategy(); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Strategys/DoubleMA_Crossover_code.cs b/Demo/QuantBox.OQ.Demo/Strategys/DoubleMA_Crossover_code.cs index c8a4a09..06bbce0 100644 --- a/Demo/QuantBox.OQ.Demo/Strategys/DoubleMA_Crossover_code.cs +++ b/Demo/QuantBox.OQ.Demo/Strategys/DoubleMA_Crossover_code.cs @@ -1,131 +1,134 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using QuantBox.OQ.Demo.Module; -using QuantBox.OQ.Demo.Helper; - -namespace QuantBox.OQ.Demo.Strategys -{ - /// - /// 双均线策略 - /// - /// 设置的是3分钟 - /// - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=113 - /// - public class DoubleMA_Crossover_code : TargetPositionModule - { - [OptimizationParameter(5, 10, 1)] - [Parameter("快均线", "SMA")] - int fastLength = 5; - - [OptimizationParameter(11, 15, 1)] - [Parameter("慢均线", "SMA")] - int slowLength = 12; - - [Parameter("交易手数")] - double Qty = 1; - - [Parameter("时间周期,请按自己的设置修改")] - int BarSize = 180; - - SMA fastSMA; - SMA slowSMA; - - static BrokerInfo BrokerInfo; - - void LoadHistoricalBars(DateTime datetime) - { - DateTime dtEnd = datetime; - DateTime dtBegin = dtEnd.AddDays(-5);//这个时间按自己的需求修改 - - TradeSeries ts = DataManager.GetHistoricalTrades(Instrument, dtBegin, dtEnd); - //个人认为这个地方应当过滤下Trade数据,去除无效的再转换成Bars - BarSeries bs = DataManager.CompressBars(ts, BarType.Time, BarSize); - BarSeries barsMin = GetBars(BarType.Time, BarSize); - foreach (Bar b in bs) - { - barsMin.Add(b); - } - } - - public override void OnStrategyStart() - { - base.OnStrategyStart(); - - // 测试用,自定义交易时间,仿真或实盘时可删除 - base.TimeHelper = new TimeHelper(new int[] { 0, 2400 },2100, 1458); - - base.TargetPosition = 0; - //base.DualPosition.Long.Qty = 0; - //base.DualPosition.Long.QtyToday = 0; - //base.DualPosition.Short.Qty = 0; - //base.DualPosition.Short.QtyToday = 0; - if(BrokerInfo == null) - { - // 使用静态的主要原因是每个实例都来取一次没有必要 - BrokerInfo = DataManager.GetBrokerInfo(); - } - if (BrokerInfo.Accounts.Count > 0) - { - BrokerAccount brokerAccount = BrokerInfo.Accounts[0]; - GetBrokerInfoHelper.Transform(brokerAccount, base.DualPosition); - } - - - LoadHistoricalBars(Clock.Now); - - BarSeries bars1min = GetBars(BarType.Time, BarSize); - - fastSMA = new SMA(bars1min, fastLength, Color.Red); - slowSMA = new SMA(bars1min, slowLength, Color.Green); - - Draw(fastSMA, 0); - Draw(slowSMA, 0); - } - - public override void OnBar(Bar bar) - { - Cross cross = fastSMA.Crosses(slowSMA, bar); - if (Cross.Above == cross) - { - base.TargetPosition = 1; - TextParameter.Text = "金叉"; - } - else if (Cross.Below == cross) - { - base.TargetPosition = -1; - TextParameter.Text = "死叉"; - } - else - { - // 保持上次的状态 - } - - base.ChangeTradingDay(); - - base.OnBar(bar); - } - - public override void OnTrade(Trade trade) - { - do - { - // 尾盘平仓 - if (0 != ExitOnClose(90,"")) - break; - - // 跟踪止损 - TrailingStop(trade.Price, 5, StopMode.Absolute, ""); - - } while (false); - - base.OnTrade(trade); - } - } - -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using QuantBox.OQ.Demo.Module; +using QuantBox.OQ.Demo.Helper; + +namespace QuantBox.OQ.Demo.Strategys +{ + /// + /// 双均线策略 + /// + /// 设置的是3分钟 + /// + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=113 + /// + public class DoubleMA_Crossover_code : TargetPositionModule + { + [OptimizationParameter(5, 10, 1)] + [Parameter("快均线", "SMA")] + int fastLength = 5; + + [OptimizationParameter(11, 15, 1)] + [Parameter("慢均线", "SMA")] + int slowLength = 12; + + [Parameter("交易手数")] + double Qty = 1; + + [Parameter("时间周期,请按自己的设置修改")] + int BarSize = 60; + + SMA fastSMA; + SMA slowSMA; + + static BrokerInfo BrokerInfo; + + void LoadHistoricalBars(DateTime datetime) + { + DateTime dtEnd = datetime; + DateTime dtBegin = dtEnd.AddDays(-5);//这个时间按自己的需求修改 + + TradeSeries ts = DataManager.GetHistoricalTrades(Instrument, dtBegin, dtEnd);//获取历史交易数据 + //个人认为这个地方应当过滤下Trade数据,去除无效的再转换成Bars + BarSeries bs = DataManager.CompressBars(ts, BarType.Time, BarSize); + BarSeries barsMin = GetBars(BarType.Time, BarSize); + foreach (Bar b in bs) + { + barsMin.Add(b); + } + } + + public override void OnStrategyStart() + { + base.OnStrategyStart();//开始基类策略 + + // 测试用,自定义交易时间,仿真或实盘时可删除 + base.TimeHelper = new TimeHelper(new int[] { 0, 2400 },2100, 1458); + + base.TargetPosition = 0; + //base.DualPosition.Long.Qty = 0; + //base.DualPosition.Long.QtyToday = 0; + //base.DualPosition.Short.Qty = 0; + //base.DualPosition.Short.QtyToday = 0; + if(BrokerInfo == null) + { + // 使用静态的主要原因是每个实例都来取一次没有必要 + BrokerInfo = DataManager.GetBrokerInfo(); + } + if (BrokerInfo.Accounts.Count > 0) + { + BrokerAccount brokerAccount = BrokerInfo.Accounts[0];//表示一组代理账户的属性,如名称、BuyingPower和位置列表。 + GetBrokerInfoHelper.Transform(brokerAccount, base.DualPosition); + } + + + LoadHistoricalBars(Clock.Now); + + BarSeries bars1min = GetBars(BarType.Time, BarSize); + + fastSMA = new SMA(bars1min, fastLength, Color.Red); + slowSMA = new SMA(bars1min, slowLength, Color.Green); + + Draw(fastSMA, 0); + Draw(slowSMA, 0); + } + /// + /// OnBar事件 + /// + /// + public override void OnBar(Bar bar) + { + Cross cross = fastSMA.Crosses(slowSMA, bar); + if (Cross.Above == cross) + { + base.TargetPosition = 1; + TextParameter.Text = "金叉"; + } + else if (Cross.Below == cross) + { + base.TargetPosition = -1; + TextParameter.Text = "死叉"; + } + else + { + // 保持上次的状态 + } + + base.ChangeTradingDay(); + + base.OnBar(bar); + } + + public override void OnTrade(Trade trade) + { + do + { + // 尾盘平仓 + if (0 != ExitOnClose(90,"")) + break; + + // 跟踪止损 + TrailingStop(trade.Price, 5, StopMode.Absolute, ""); + + } while (false); + + base.OnTrade(trade); + } + } + +} diff --git a/Demo/QuantBox.OQ.Demo/Strategys/DrawCircles_code.cs b/Demo/QuantBox.OQ.Demo/Strategys/DrawCircles_code.cs index 695e3a5..7eb69e7 100644 --- a/Demo/QuantBox.OQ.Demo/Strategys/DrawCircles_code.cs +++ b/Demo/QuantBox.OQ.Demo/Strategys/DrawCircles_code.cs @@ -1,35 +1,35 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -namespace QuantBox.OQ.Demo.Strategys -{ - /// - /// 在K线上将每天的第一个K线上画点,标记出来 - /// - public class DrawCircles_code : Strategy - { - int day = -1; - public TimeSeries ts = new TimeSeries(); - - public override void OnStrategyStart() - { - ts.Width = 5; - Draw(ts, 0, DrawStyle.Circles); - } - - public override void OnBar(Bar bar) - { - if (bar.DateTime.Day != day) - { - day = bar.DateTime.Day; - ts.Add(bar.DateTime, bar.High + 1); - } - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +namespace QuantBox.OQ.Demo.Strategys +{ + /// + /// 在K线上将每天的第一个K线上画点,标记出来 + /// + public class DrawCircles_code : Strategy + { + int day = -1; + public TimeSeries ts = new TimeSeries(); + + public override void OnStrategyStart() + { + ts.Width = 5; + Draw(ts, 0, DrawStyle.Circles); + } + + public override void OnBar(Bar bar) + { + if (bar.DateTime.Day != day) + { + day = bar.DateTime.Day;//获取bqr序列的日期 + ts.Add(bar.DateTime, bar.High + 1); + } + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Strategys/DualThrust_OpenRange_code.cs b/Demo/QuantBox.OQ.Demo/Strategys/DualThrust_OpenRange_code.cs index 0eae679..d80c364 100644 --- a/Demo/QuantBox.OQ.Demo/Strategys/DualThrust_OpenRange_code.cs +++ b/Demo/QuantBox.OQ.Demo/Strategys/DualThrust_OpenRange_code.cs @@ -1,196 +1,196 @@ -using System; -using System.Drawing; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -using QuantBox.OQ.Demo.Indicator; -using QuantBox.OQ.Demo.Module; -using QuantBox.OQ.Demo.Helper; - -namespace QuantBox.OQ.Demo.Strategys -{ - /// - /// Dual Thrust & Open Range Break - /// - /// 添加日线,添加1分钟线 - /// 在属性面板中设置策略类型,是DualThrust还是OpenRangeBreak. - /// 当设置成OpenRangeBreak时,N设置无效 - /// - /// 没有历史数据加载的部分,请参考论坛上提到的从模拟切换到实盘的方法 - /// - /// 网上对这两个策略的配图 - /// http://gzqh.cnfol.com/111101/175,1787,11039812,00.shtml - /// 论坛上DualThrust的TB版源码 - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=195 - /// 论坛上OpenRangeBreak中文描述 - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=398 - /// - public class DualThrust_OpenRange_code : TargetPositionModule - { - public enum StrategyType - { - DualThrust, - OpenRangeBreak, - } - - [Parameter] - StrategyType strategyType = StrategyType.DualThrust; - [OptimizationParameter(0.4, 0.9, 0.1)] - [Parameter("K1,上轨的参数")] - double K1 = 0.5; - [OptimizationParameter(0.4, 0.9, 0.1)] - [Parameter("K2,下轨的参数")] - double K2 = 0.5; - [Parameter] - double Range = 10; - [Parameter] - int N = 5; - [Parameter] - double Qty = 1; - - TimeSeries UpSeries; - TimeSeries DownSeries; - TimeSeries RangeSeries; - - PC HH; - PC HC; - PC LC; - PC LL; - - double UpLine = double.NaN; - double DownLine = double.NaN; - - BarSeries bars86400; - - public override void OnStrategyStart() - { - base.OnStrategyStart(); - - // 测试用,自定义交易时间,仿真或实盘时可删除 - base.TimeHelper = new TimeHelper(new int[] { 0, 2400 },2100, 1458); - - base.TargetPosition = 0; - base.DualPosition.Long.Qty = 0; - base.DualPosition.Short.Qty = 0; - - UpSeries = new TimeSeries("Up"); - DownSeries = new TimeSeries("Down"); - RangeSeries = new TimeSeries("Range"); - - int n = N; - if (StrategyType.OpenRangeBreak == strategyType) - { - n = 1; - } - - bars86400 = GetBars(BarType.Time, 86400); - HH = new PC(bars86400, n, BarData.High, PC.CalcType.Max, PC.UseLast.Yes); - HC = new PC(bars86400, n, BarData.Close, PC.CalcType.Max, PC.UseLast.Yes); - LC = new PC(bars86400, n, BarData.Close, PC.CalcType.Min, PC.UseLast.Yes); - LL = new PC(bars86400, n, BarData.Low, PC.CalcType.Min, PC.UseLast.Yes); - - - Draw(UpSeries, 0); - Draw(DownSeries, 0); - Draw(RangeSeries, 2); - } - - public override void OnBarOpen(Bar bar) - { - do - { - if (86400 == bar.Size) - { - if (HH.Count < 1) - break; - - if (StrategyType.OpenRangeBreak == strategyType) - { - Range = HH.Last - LL.Last; - } - else - { - Range = Math.Max(HH.Last - LC.Last, HC.Last - LL.Last); - } - - double dbOpen = bar.Open; - // 如果昨天波动过小,调整一下最小range - Range = Math.Max(Range, dbOpen * 0.01 * 0.2); - - UpLine = dbOpen + K1 * Range; - DownLine = dbOpen - K2 * Range; - - base.ChangeTradingDay(); - } - } while (false); - - base.OnBarOpen(bar); - } - - public override void OnBar(Bar bar) - { - do - { - // 尾盘平仓 - if (0 != ExitOnClose(60,"")) - break; - - // 日线数据上不处理 - if (86400 == bar.Size) - break; - - // 数据 - if (double.IsNaN(UpLine)) - break; - - UpSeries.Add(bar.DateTime, UpLine); - DownSeries.Add(bar.DateTime, DownLine); - RangeSeries.Add(bar.DateTime, Range); - - if (bar.Close > UpLine) - { - TargetPosition = 1; - TextParameter.Text = "突破上轨,多头"; - } - else if (bar.Close < DownLine) - { - TargetPosition = -1; - TextParameter.Text = "突破下轨,空头"; - } - else - { - // 处于中间状态的怎么处理? - } - } - while (false); - - if (Mode == StrategyMode.Simulation) - { - // 从模拟切换实盘时用 - //return; - } - - base.OnBar(bar); - } - - - public override void OnTrade(Trade trade) - { - do - { - // 尾盘平仓 - if (0 != ExitOnClose(300,"")) - break; - - // 跟踪止损 - TrailingStop(trade.Price, 5, StopMode.Absolute, ""); - - } while (false); - - - base.OnTrade(trade); - } - } -} +using System; +using System.Drawing; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +using QuantBox.OQ.Demo.Indicator; +using QuantBox.OQ.Demo.Module; +using QuantBox.OQ.Demo.Helper; + +namespace QuantBox.OQ.Demo.Strategys +{ + /// + /// Dual Thrust & Open Range Break + /// + /// 添加日线,添加1分钟线 + /// 在属性面板中设置策略类型,是DualThrust还是OpenRangeBreak. + /// 当设置成OpenRangeBreak时,N设置无效 + /// + /// 没有历史数据加载的部分,请参考论坛上提到的从模拟切换到实盘的方法 + /// + /// 网上对这两个策略的配图 + /// http://gzqh.cnfol.com/111101/175,1787,11039812,00.shtml + /// 论坛上DualThrust的TB版源码 + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=195 + /// 论坛上OpenRangeBreak中文描述 + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=398 + /// + public class DualThrust_OpenRange_code : TargetPositionModule + { + public enum StrategyType + { + DualThrust, + OpenRangeBreak, + } + + [Parameter] + StrategyType strategyType = StrategyType.DualThrust; + [OptimizationParameter(0.4, 0.9, 0.1)] + [Parameter("K1,上轨的参数")] + double K1 = 0.5; + [OptimizationParameter(0.4, 0.9, 0.1)] + [Parameter("K2,下轨的参数")] + double K2 = 0.5; + [Parameter] + double Range = 10; + [Parameter] + int N = 5; + [Parameter] + double Qty = 1; + + TimeSeries UpSeries; + TimeSeries DownSeries; + TimeSeries RangeSeries; + + PC HH; + PC HC; + PC LC; + PC LL; + + double UpLine = double.NaN; + double DownLine = double.NaN; + + BarSeries bars86400; + + public override void OnStrategyStart() + { + base.OnStrategyStart(); + + // 测试用,自定义交易时间,仿真或实盘时可删除 + base.TimeHelper = new TimeHelper(new int[] { 0, 2400 },2100, 1458); + + base.TargetPosition = 0; + base.DualPosition.Long.Qty = 0; + base.DualPosition.Short.Qty = 0; + + UpSeries = new TimeSeries("Up"); + DownSeries = new TimeSeries("Down"); + RangeSeries = new TimeSeries("Range"); + + int n = N; + if (StrategyType.OpenRangeBreak == strategyType) + { + n = 1; + } + + bars86400 = GetBars(BarType.Time, 86400); + HH = new PC(bars86400, n, BarData.High, PC.CalcType.Max, PC.UseLast.Yes); + HC = new PC(bars86400, n, BarData.Close, PC.CalcType.Max, PC.UseLast.Yes); + LC = new PC(bars86400, n, BarData.Close, PC.CalcType.Min, PC.UseLast.Yes); + LL = new PC(bars86400, n, BarData.Low, PC.CalcType.Min, PC.UseLast.Yes); + + + Draw(UpSeries, 0); + Draw(DownSeries, 0); + Draw(RangeSeries, 2); + } + + public override void OnBarOpen(Bar bar) + { + do + { + if (86400 == bar.Size) + { + if (HH.Count < 1) + break; + + if (StrategyType.OpenRangeBreak == strategyType) + { + Range = HH.Last - LL.Last; + } + else + { + Range = Math.Max(HH.Last - LC.Last, HC.Last - LL.Last); + } + + double dbOpen = bar.Open; + // 如果昨天波动过小,调整一下最小range + Range = Math.Max(Range, dbOpen * 0.01 * 0.2); + + UpLine = dbOpen + K1 * Range; + DownLine = dbOpen - K2 * Range; + + base.ChangeTradingDay(); + } + } while (false); + + base.OnBarOpen(bar); + } + + public override void OnBar(Bar bar) + { + do + { + // 尾盘平仓 + if (0 != ExitOnClose(60,"")) + break; + + // 日线数据上不处理 + if (86400 == bar.Size) + break; + + // 数据 + if (double.IsNaN(UpLine)) + break; + + UpSeries.Add(bar.DateTime, UpLine); + DownSeries.Add(bar.DateTime, DownLine); + RangeSeries.Add(bar.DateTime, Range); + + if (bar.Close > UpLine) + { + TargetPosition = 1; + TextParameter.Text = "突破上轨,多头"; + } + else if (bar.Close < DownLine) + { + TargetPosition = -1; + TextParameter.Text = "突破下轨,空头"; + } + else + { + // 处于中间状态的怎么处理? + } + } + while (false); + + if (Mode == StrategyMode.Simulation) + { + // 从模拟切换实盘时用 + //return; + } + + base.OnBar(bar); + } + + + public override void OnTrade(Trade trade) + { + do + { + // 尾盘平仓 + if (0 != ExitOnClose(300,"")) + break; + + // 跟踪止损 + TrailingStop(trade.Price, 5, StopMode.Absolute, ""); + + } while (false); + + + base.OnTrade(trade); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Strategys/DynamicBreakOut2_code.cs b/Demo/QuantBox.OQ.Demo/Strategys/DynamicBreakOut2_code.cs index 0ce213d..8bd320c 100644 --- a/Demo/QuantBox.OQ.Demo/Strategys/DynamicBreakOut2_code.cs +++ b/Demo/QuantBox.OQ.Demo/Strategys/DynamicBreakOut2_code.cs @@ -1,151 +1,151 @@ -using System; -using System.Drawing; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; - -using QuantBox.OQ.Demo.Indicator; -using QuantBox.OQ.Demo.Module; -using QuantBox.OQ.Demo.Helper; - -namespace QuantBox.OQ.Demo.Strategys -{ - /// - /// 自适应动态突破系统 - /// - /// 添加一个日线,再添加一个1分钟 - /// - /// 论坛上的TB代码 - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=193 - /// 网上的TS代码 - /// http://www.programtrading.tw/viewtopic.php?t=504 - /// - public class DynamicBreakOut2_code : TargetPositionModule - { - [Parameter("指标窗口长度(LookBackDays)的上限")] - int ceilingAmt = 60; - [Parameter("指标窗口长度(LookBackDays)的下限")] - int floorAmt = 20; - [Parameter("布林线参数")] - double bolBandTrig = 2; - [Parameter("合约数目")] - double Qty = 1; - - // 指标窗口长度(LookBackDays)的初始值 - int lookBackDays = 20; - - SMD smd30; - LookBackDays lbd; - DynamicBBU dbbu; - - BarSeries bars86400; - - TimeSeries upBandSeries; - TimeSeries dnBandSeries; - TimeSeries buyPointSeries; - TimeSeries sellPointSeries; - - public override void OnStrategyStart() - { - base.OnStrategyStart(); - - // 测试用,自定义交易时间,仿真或实盘时可删除 - base.TimeHelper = new TimeHelper(new int[] { 0, 2400 }, 2100, 1458); - - base.TargetPosition = 0; - base.DualPosition.Long.Qty = 0; - base.DualPosition.Short.Qty = 0; - - bars86400 = GetBars(BarType.Time, 86400); - - smd30 = new SMD(bars86400, 30); - lbd = new LookBackDays(smd30, lookBackDays, floorAmt, ceilingAmt); - dbbu = new DynamicBBU(lbd, bars86400, bolBandTrig, BarData.Close); - - Draw(smd30, 2); - Draw(lbd, 3); - Draw(dbbu.SMA, 0); - Draw(dbbu.BBL, 0); - Draw(dbbu, 0); - - upBandSeries = new TimeSeries("upBandSeries"); - dnBandSeries = new TimeSeries("dnBandSeries"); - buyPointSeries = new TimeSeries("buyPointSeries"); - sellPointSeries = new TimeSeries("sellPointSeries"); - - upBandSeries.Color = Color.Red; - dnBandSeries.Color = Color.Red; - - Draw(upBandSeries, 0); - Draw(dnBandSeries, 0); - Draw(buyPointSeries, 0); - Draw(sellPointSeries, 0); - - base.OnStrategyStart(); - } - - public override void OnBar(Bar bar) - { - if (bar.Size == 86400) - { - base.ChangeTradingDay(); - return; - } - - if (lbd.Count < 1 || dbbu.Count < 1) - return; - - int lookBackDaysInt = (int)lbd.Last; - int nEnd = bars86400.Count - 1; - int nBegin = nEnd - lookBackDays + 1; - - double buyPoint = bars86400.HighestHigh(nBegin, nEnd); - double sellPoint = bars86400.LowestLow(nBegin, nEnd); - double longLiqPoint = dbbu.SMA.Last; - double shortLiqPoint = dbbu.SMA.Last; - double upBand = dbbu.Last; - double dnBand = dbbu.BBL.Last; - - upBandSeries.Add(bar.DateTime, upBand); - dnBandSeries.Add(bar.DateTime, dnBand); - buyPointSeries.Add(bar.DateTime, buyPoint); - sellPointSeries.Add(bar.DateTime, sellPoint); - - do - { - if (GetCurrentQty()>0) - { - if (bar.Close < longLiqPoint) - { - TargetPosition = 0; - TextParameter.Text = "低于多头流动点"; - } - } - else if (GetCurrentQty() < 0) - { - if (bar.Close > shortLiqPoint) - { - TargetPosition = 0; - TextParameter.Text = "高于空头流动点"; - } - } - else - { - if (bar.Close > upBand) - { - TargetPosition = 1; - TextParameter.Text = "突破上轨开仓"; - } - else if (bar.Close < dnBand) - { - TargetPosition = -1; - TextParameter.Text = "突破下轨开仓"; - } - } - } while (false); - - base.OnBar(bar); - } - } -} +using System; +using System.Drawing; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; + +using QuantBox.OQ.Demo.Indicator; +using QuantBox.OQ.Demo.Module; +using QuantBox.OQ.Demo.Helper; + +namespace QuantBox.OQ.Demo.Strategys +{ + /// + /// 自适应动态突破系统 + /// + /// 添加一个日线,再添加一个1分钟 + /// + /// 论坛上的TB代码 + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=193 + /// 网上的TS代码 + /// http://www.programtrading.tw/viewtopic.php?t=504 + /// + public class DynamicBreakOut2_code : TargetPositionModule + { + [Parameter("指标窗口长度(LookBackDays)的上限")] + int ceilingAmt = 60; + [Parameter("指标窗口长度(LookBackDays)的下限")] + int floorAmt = 20; + [Parameter("布林线参数")] + double bolBandTrig = 2; + [Parameter("合约数目")] + double Qty = 1; + + // 指标窗口长度(LookBackDays)的初始值 + int lookBackDays = 20; + + SMD smd30; + LookBackDays lbd; + DynamicBBU dbbu; + + BarSeries bars86400; + + TimeSeries upBandSeries; + TimeSeries dnBandSeries; + TimeSeries buyPointSeries; + TimeSeries sellPointSeries; + + public override void OnStrategyStart() + { + base.OnStrategyStart(); + + // 测试用,自定义交易时间,仿真或实盘时可删除 + base.TimeHelper = new TimeHelper(new int[] { 0, 2400 }, 2100, 1458); + + base.TargetPosition = 0; + base.DualPosition.Long.Qty = 0; + base.DualPosition.Short.Qty = 0; + + bars86400 = GetBars(BarType.Time, 86400); + + smd30 = new SMD(bars86400, 30); + lbd = new LookBackDays(smd30, lookBackDays, floorAmt, ceilingAmt); + dbbu = new DynamicBBU(lbd, bars86400, bolBandTrig, BarData.Close); + + Draw(smd30, 2); + Draw(lbd, 3); + Draw(dbbu.SMA, 0); + Draw(dbbu.BBL, 0); + Draw(dbbu, 0); + + upBandSeries = new TimeSeries("upBandSeries"); + dnBandSeries = new TimeSeries("dnBandSeries"); + buyPointSeries = new TimeSeries("buyPointSeries"); + sellPointSeries = new TimeSeries("sellPointSeries"); + + upBandSeries.Color = Color.Red; + dnBandSeries.Color = Color.Red; + + Draw(upBandSeries, 0); + Draw(dnBandSeries, 0); + Draw(buyPointSeries, 0); + Draw(sellPointSeries, 0); + + base.OnStrategyStart(); + } + + public override void OnBar(Bar bar) + { + if (bar.Size == 86400) + { + base.ChangeTradingDay(); + return; + } + + if (lbd.Count < 1 || dbbu.Count < 1) + return; + + int lookBackDaysInt = (int)lbd.Last; + int nEnd = bars86400.Count - 1; + int nBegin = nEnd - lookBackDays + 1; + + double buyPoint = bars86400.HighestHigh(nBegin, nEnd); + double sellPoint = bars86400.LowestLow(nBegin, nEnd); + double longLiqPoint = dbbu.SMA.Last; + double shortLiqPoint = dbbu.SMA.Last; + double upBand = dbbu.Last; + double dnBand = dbbu.BBL.Last; + + upBandSeries.Add(bar.DateTime, upBand); + dnBandSeries.Add(bar.DateTime, dnBand); + buyPointSeries.Add(bar.DateTime, buyPoint); + sellPointSeries.Add(bar.DateTime, sellPoint); + + do + { + if (GetCurrentQty()>0) + { + if (bar.Close < longLiqPoint) + { + TargetPosition = 0; + TextParameter.Text = "低于多头流动点"; + } + } + else if (GetCurrentQty() < 0) + { + if (bar.Close > shortLiqPoint) + { + TargetPosition = 0; + TextParameter.Text = "高于空头流动点"; + } + } + else + { + if (bar.Close > upBand) + { + TargetPosition = 1; + TextParameter.Text = "突破上轨开仓"; + } + else if (bar.Close < dnBand) + { + TargetPosition = -1; + TextParameter.Text = "突破下轨开仓"; + } + } + } while (false); + + base.OnBar(bar); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Strategys/PairTrading2_code.cs b/Demo/QuantBox.OQ.Demo/Strategys/PairTrading2_code.cs index 643d6bf..0388044 100644 --- a/Demo/QuantBox.OQ.Demo/Strategys/PairTrading2_code.cs +++ b/Demo/QuantBox.OQ.Demo/Strategys/PairTrading2_code.cs @@ -33,7 +33,7 @@ public class PairTrading2_code : TargetPositionModule // 直接使用这种static比使用Global要快 static PairTrading2_code S1; static PairTrading2_code S2; - + public override void OnStrategyStart() { base.OnStrategyStart(); diff --git a/Demo/QuantBox.OQ.Demo/Strategys/PairTrading_code.cs b/Demo/QuantBox.OQ.Demo/Strategys/PairTrading_code.cs index 0bdc9dc..56012e2 100644 --- a/Demo/QuantBox.OQ.Demo/Strategys/PairTrading_code.cs +++ b/Demo/QuantBox.OQ.Demo/Strategys/PairTrading_code.cs @@ -1,107 +1,107 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; -using System.Collections.Generic; - -using OpenQuant.API; -using OpenQuant.API.Indicators; - -namespace QuantBox.OQ.Demo.Strategys -{ - /// - /// 配对交易示例 - /// 主要靠静态变量来实现引用两个合约的数据,并计算价差。 - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=345 - /// - /// 现在已经不推荐使用此方法,请参考MySpreadMarketData.cs - /// - public class PairTrading_code:Strategy - { - Instrument Instrument1 = InstrumentManager.Instruments["cu000"]; - Instrument Instrument2 = InstrumentManager.Instruments["zn000"]; - - //static PairTrading_code Strategy1; - //static PairTrading_code Strategy2; - static BarSeries BarSeries1; - static BarSeries BarSeries2; - - static TimeSeries spreadSeries; - - static Dictionary _bars; - - [Parameter("两合约价格序列回归方程的系数")] - double Slope = 4.325347; - - [Parameter("两合约价格序列回归方程的常数项")] - double Const = -8358.336; - - [Parameter("时间窗口")] - int Length = 100; - - int barSize = 60; - - SMA sma; - - public override void OnStrategyStart() - { - if (Instrument1 == Instrument) - { - //Strategy1 = this; - BarSeries1 = GetBars(BarType.Time, barSize); - } - else if (Instrument2 == Instrument) - { - //Strategy2 = this; - BarSeries2 = GetBars(BarType.Time, barSize); - } - else - { - Console.WriteLine("合约错误!" + Instrument); - } - - spreadSeries = new TimeSeries("spread"); - _bars = new Dictionary(); - sma = new SMA(spreadSeries, Length); - - Draw(spreadSeries, 2); - Draw(sma, 2); - } - - double Calculate(Bar bar1, Bar bar2) - { - return Calculate(bar1.Close,bar2.Close); - } - - double Calculate(double db1, double db2) - { - return db1 - db2 * Slope - Const; - } - - public override void OnBar(Bar bar) - { - _bars[Instrument.Symbol] = bar.Close; - - } - - public override void OnBarSlice(long size) - { - if (Instrument1 == Instrument) - return; - - double b1, b2; - if (_bars.TryGetValue("cu000", out b1) - && _bars.TryGetValue("zn000", out b2)) - { - spreadSeries.Add(Clock.Now, Calculate(b1, b2)); - } - - if (sma.Count < 1) - return; - - //操作 - //Sell(Instrument2,Qty2,"O|卖开"); - //Buy(Instrument1,Qty1,"O|买开"); - } - } -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; +using System.Collections.Generic; + +using OpenQuant.API; +using OpenQuant.API.Indicators; + +namespace QuantBox.OQ.Demo.Strategys +{ + /// + /// 配对交易示例 + /// 主要靠静态变量来实现引用两个合约的数据,并计算价差。 + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=345 + /// + /// 现在已经不推荐使用此方法,请参考MySpreadMarketData.cs + /// + public class PairTrading_code:Strategy + { + Instrument Instrument1 = InstrumentManager.Instruments["cu000"]; + Instrument Instrument2 = InstrumentManager.Instruments["zn000"]; + + //static PairTrading_code Strategy1; + //static PairTrading_code Strategy2; + static BarSeries BarSeries1; + static BarSeries BarSeries2; + + static TimeSeries spreadSeries; + + static Dictionary _bars; + + [Parameter("两合约价格序列回归方程的系数")] + double Slope = 4.325347; + + [Parameter("两合约价格序列回归方程的常数项")] + double Const = -8358.336; + + [Parameter("时间窗口")] + int Length = 100; + + int barSize = 60; + + SMA sma; + + public override void OnStrategyStart() + { + if (Instrument1 == Instrument) + { + //Strategy1 = this; + BarSeries1 = GetBars(BarType.Time, barSize); + } + else if (Instrument2 == Instrument) + { + //Strategy2 = this; + BarSeries2 = GetBars(BarType.Time, barSize); + } + else + { + Console.WriteLine("合约错误!" + Instrument); + } + + spreadSeries = new TimeSeries("spread"); + _bars = new Dictionary(); + sma = new SMA(spreadSeries, Length); + + Draw(spreadSeries, 2); + Draw(sma, 2); + } + + double Calculate(Bar bar1, Bar bar2) + { + return Calculate(bar1.Close,bar2.Close); + } + + double Calculate(double db1, double db2) + { + return db1 - db2 * Slope - Const; + } + + public override void OnBar(Bar bar) + { + _bars[Instrument.Symbol] = bar.Close; + + } + + public override void OnBarSlice(long size) + { + if (Instrument1 == Instrument) + return; + + double b1, b2; + if (_bars.TryGetValue("cu000", out b1) + && _bars.TryGetValue("zn000", out b2)) + { + spreadSeries.Add(Clock.Now, Calculate(b1, b2)); + } + + if (sma.Count < 1) + return; + + //操作 + //Sell(Instrument2,Qty2,"O|卖开"); + //Buy(Instrument1,Qty1,"O|买开"); + } + } +} diff --git a/Demo/QuantBox.OQ.Demo/Strategys/RBreaker_code.cs b/Demo/QuantBox.OQ.Demo/Strategys/RBreaker_code.cs index 3e6c9b2..9ecb0d3 100644 --- a/Demo/QuantBox.OQ.Demo/Strategys/RBreaker_code.cs +++ b/Demo/QuantBox.OQ.Demo/Strategys/RBreaker_code.cs @@ -1,251 +1,256 @@ -using System; -using System.Drawing; -using System.Reflection; -using System.Windows.Forms; - -using OpenQuant.API; -using OpenQuant.API.Indicators; -using OpenQuant.API.Plugins; -using QuantBox.OQ.Demo.Module; -using QuantBox.OQ.Demo.Helper; - -namespace QuantBox.OQ.Demo.Strategys -{ - /// - /// R-Breaker - /// - /// 使用方法,添加一个日线,添加一个1分钟线 - /// 将第一天前一天的收盘、最高、最低填好 - /// 由于历史的收高低是手工填写的,所以整个代码中没有加载历史数据的代码, - /// 如果想长期无人值守,只要在点运行前改正好上一交易日的收高低即可 - /// - /// 网上金字塔版,带图 - /// http://www.yafco.com/show.php?contentid=261740 - /// 论坛上的TB版 - /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=194 - /// - public class RBreaker_code : TargetPositionModule - { - //第一次运行时,前一天的开高底收 - [Parameter("前一天最高价", "PreDay")] - double preDayHigh = 0; - [Parameter("前一天最低价", "PreDay")] - double preDayLow = 0; - [Parameter("前一天收盘价", "PreDay")] - double preDayClose = 0; - - [OptimizationParameter(0.3, 0.5, 0.05)] - [Parameter] - double f1 = 0.35; - [Parameter] - [OptimizationParameter(0.05, 0.09, 0.01)] - double f2 = 0.07; - [Parameter] - [OptimizationParameter(0.10, 0.15, 0.01)] - double f3 = 0.12; - [Parameter] - double Qty = 1; - - double reverse = 0.5; - double rangemin = 0.2; - double xdiv = 3; - - double div = 3; - double i_reverse = 1; - double i_rangemin = 1; - bool rfilter; - - TimeSeries S1; - TimeSeries B1; - - long barSize = long.MaxValue; - - #region R-Breaker - TimeSeries ssetup; - TimeSeries bsetup; - TimeSeries senter; - TimeSeries benter; - TimeSeries bbreak; - TimeSeries sbreak; - - double _ssetup = double.NaN; - double _bsetup = double.NaN; - double _senter = double.NaN; - double _benter = double.NaN; - double _bbreak = double.NaN; - double _sbreak = double.NaN; - - void UpdateAtDaily_RBreaker(Bar bar) - { - preDayHigh = bar.High; - preDayLow = bar.Low; - preDayClose = bar.Close; - - Update6Line(); - } - - void Update6Line() - { - //先计算,时候到了再放到序列中 - _ssetup = preDayHigh + f1 * (preDayClose - preDayLow); - _bsetup = preDayLow - f1 * (preDayHigh - preDayClose); - - _senter = (1 + f2) / 2.0 * (preDayHigh + preDayClose) - f2 * preDayLow; - _benter = (1 + f2) / 2.0 * (preDayLow + preDayClose) - f2 * preDayHigh; - - _bbreak = _ssetup + f3 * (_ssetup - _bsetup); - _sbreak = _bsetup - f3 * (_ssetup - _bsetup); - } - - void UpdateAtBar_RBreaker(Bar bar) - { - ssetup.Add(bar.DateTime, _ssetup); - bsetup.Add(bar.DateTime, _bsetup); - senter.Add(bar.DateTime, _senter); - benter.Add(bar.DateTime, _benter); - bbreak.Add(bar.DateTime, _bbreak); - sbreak.Add(bar.DateTime, _sbreak); - } - #endregion - - #region HighLow - double HighToday = double.MinValue; - double LowToday = double.MaxValue; - void UpdateAtDaily_HighLow(Bar bar) - { - HighToday = double.MinValue; - LowToday = double.MaxValue; - } - void UpdateAtBar_HighLow(Bar bar) - { - - HighToday = Math.Max(HighToday, bar.High); - LowToday = Math.Min(LowToday, bar.Low); - } - #endregion - - public override void OnStrategyStart() - { - base.OnStrategyStart(); - - // 测试用,自定义交易时间,仿真或实盘时可删除 - base.TimeHelper = new TimeHelper(new int[] { 0, 2400 }, 2100, 1458); - - base.TargetPosition = 0; - base.DualPosition.Long.Qty = 0; - base.DualPosition.Short.Qty = 0; - - // 自动得到当时时间窗口大小 - foreach (BarRequest barRequest in DataRequests.BarRequests) - { - barSize = Math.Min(barSize, barRequest.BarSize); - } - Console.WriteLine("barSize = {0}", barSize); - - Update6Line(); - - ssetup = new TimeSeries("观察卖出价", Color.Green); - bsetup = new TimeSeries("观察买入价", Color.Green); - bbreak = new TimeSeries("突破买入价", Color.Red); - sbreak = new TimeSeries("突破卖出价", Color.Red); - senter = new TimeSeries("反转卖出价", Color.Black); - benter = new TimeSeries("反转买入价", Color.Black); - - S1 = new TimeSeries("S1", Color.Blue); - B1 = new TimeSeries("B1", Color.Blue); - - Draw(ssetup, 0); - Draw(bsetup, 0); - Draw(bbreak, 0); - Draw(sbreak, 0); - Draw(senter, 0); - Draw(benter, 0); - - Draw(S1, 0); - Draw(B1, 0); - } - - public override void OnBarOpen(Bar bar) - { - if (86400 == bar.Size) - { - i_reverse = reverse * (bar.Open / 100.0); - i_rangemin = rangemin * (bar.Open / 100.0); - div = Math.Max(xdiv, 1); - - base.ChangeTradingDay(); - } - } - - public override void OnBar(Bar bar) - { - if (86400 == bar.Size) - { - //表示今天结束了,要记下今天的开高底收和明天可以用到的价格 - UpdateAtDaily_RBreaker(bar); - UpdateAtDaily_HighLow(bar); - - rfilter = (preDayHigh - preDayLow) >= i_rangemin; - return; - } - - UpdateAtBar_RBreaker(bar); - UpdateAtBar_HighLow(bar); - - double _S1 = _senter + (HighToday - _ssetup) / div; - double _B1 = _benter - (_bsetup - LowToday) / div; - - S1.Add(bar.DateTime, _S1); - B1.Add(bar.DateTime, _B1); - - do - { - // 尾盘平仓 - if (0 != ExitOnClose(60,"")) - break; - - if (GetCurrentQty() > 0) - { - if ((HighToday > _ssetup && bar.Close < _S1) - || bar.Close < _sbreak) - { - string text = string.Format("{0}>{1}&&{2}<{3}", - HighToday, _ssetup, - bar.Close, _S1); - TargetPosition = -1; - TextParameter.Text = text; - } - } - else if (GetCurrentQty() < 0) - { - if ((LowToday < _bsetup && bar.Close > _B1) - || bar.Close > _bbreak) - { - string text = string.Format("{0}>{1}&&{2}<{3}", - LowToday, _bsetup, - bar.Close, _B1); - TargetPosition = 1; - TextParameter.Text = text; - } - } - else - { - if (bar.Close > _bbreak) - { - TargetPosition = 1; - TextParameter.Text = string.Format("{0}>{1}", bar.Close, _bbreak); - } - if (bar.Close < _sbreak) - { - TargetPosition = -1; - TextParameter.Text = string.Format("{0}<{1}", bar.Close, _bbreak); - } - } - - } while (false); - - base.OnBar(bar); - } - } - -} +using System; +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; + +using OpenQuant.API; +using OpenQuant.API.Indicators; +using OpenQuant.API.Plugins; +using QuantBox.OQ.Demo.Module; +using QuantBox.OQ.Demo.Helper; + +namespace QuantBox.OQ.Demo.Strategys +{ + /// + /// R-Breaker + /// + /// 使用方法,添加一个日线,添加一个1分钟线 + /// 将第一天前一天的收盘、最高、最低填好 + /// 由于历史的收高低是手工填写的,所以整个代码中没有加载历史数据的代码, + /// 如果想长期无人值守,只要在点运行前改正好上一交易日的收高低即可 + /// + /// 网上金字塔版,带图 + /// http://www.yafco.com/show.php?contentid=261740 + /// 论坛上的TB版 + /// http://www.smartquant.cn/forum/forum.php?mod=viewthread&tid=194 + /// + public class RBreaker_code : TargetPositionModule + { + //第一次运行时,前一天的开高底收 + [Parameter("前一天最高价", "PreDay")] + /// + /// 前一天最高价 + /// + double preDayHigh = 0; + [Parameter("前一天最低价", "PreDay")] + double preDayLow = 0; + [Parameter("前一天收盘价", "PreDay")] + double preDayClose = 0; + + [OptimizationParameter(0.3, 0.5, 0.05)] + [Parameter] + double f1 = 0.35; + [Parameter] + [OptimizationParameter(0.05, 0.09, 0.01)] + double f2 = 0.07; + [Parameter] + [OptimizationParameter(0.10, 0.15, 0.01)] + double f3 = 0.12; + [Parameter] + double Qty = 1; + + double reverse = 0.5; + double rangemin = 0.2; + double xdiv = 3; + + double div = 3; + double i_reverse = 1; + double i_rangemin = 1; + bool rfilter; + + TimeSeries S1; + TimeSeries B1; + + long barSize = long.MaxValue; + + #region R-Breaker + TimeSeries ssetup; + TimeSeries bsetup; + TimeSeries senter; + TimeSeries benter; + TimeSeries bbreak; + TimeSeries sbreak; + + double _ssetup = double.NaN; + double _bsetup = double.NaN; + double _senter = double.NaN; + double _benter = double.NaN; + double _bbreak = double.NaN; + double _sbreak = double.NaN; + + void UpdateAtDaily_RBreaker(Bar bar) + { + preDayHigh = bar.High; + preDayLow = bar.Low; + preDayClose = bar.Close; + + Update6Line(); + } + /// + /// + /// + void Update6Line() + { + //先计算,时候到了再放到序列中 + _ssetup = preDayHigh + f1 * (preDayClose - preDayLow); + _bsetup = preDayLow - f1 * (preDayHigh - preDayClose); + + _senter = (1 + f2) / 2.0 * (preDayHigh + preDayClose) - f2 * preDayLow; + _benter = (1 + f2) / 2.0 * (preDayLow + preDayClose) - f2 * preDayHigh; + + _bbreak = _ssetup + f3 * (_ssetup - _bsetup); + _sbreak = _bsetup - f3 * (_ssetup - _bsetup); + } + + void UpdateAtBar_RBreaker(Bar bar) + { + ssetup.Add(bar.DateTime, _ssetup); + bsetup.Add(bar.DateTime, _bsetup); + senter.Add(bar.DateTime, _senter); + benter.Add(bar.DateTime, _benter); + bbreak.Add(bar.DateTime, _bbreak); + sbreak.Add(bar.DateTime, _sbreak); + } + #endregion + + #region HighLow + double HighToday = double.MinValue; + double LowToday = double.MaxValue; + void UpdateAtDaily_HighLow(Bar bar) + { + HighToday = double.MinValue; + LowToday = double.MaxValue; + } + void UpdateAtBar_HighLow(Bar bar) + { + + HighToday = Math.Max(HighToday, bar.High); + LowToday = Math.Min(LowToday, bar.Low); + } + #endregion + + public override void OnStrategyStart() + { + base.OnStrategyStart(); + + // 测试用,自定义交易时间,仿真或实盘时可删除 + base.TimeHelper = new TimeHelper(new int[] { 0, 2400 }, 2100, 1458); + + base.TargetPosition = 0; + base.DualPosition.Long.Qty = 0; + base.DualPosition.Short.Qty = 0; + + // 自动得到当时时间窗口大小 + foreach (BarRequest barRequest in DataRequests.BarRequests) + { + barSize = Math.Min(barSize, barRequest.BarSize); + } + Console.WriteLine("barSize = {0}", barSize); + + Update6Line(); + + ssetup = new TimeSeries("观察卖出价", Color.Green); + bsetup = new TimeSeries("观察买入价", Color.Green); + bbreak = new TimeSeries("突破买入价", Color.Red); + sbreak = new TimeSeries("突破卖出价", Color.Red); + senter = new TimeSeries("反转卖出价", Color.Black); + benter = new TimeSeries("反转买入价", Color.Black); + + S1 = new TimeSeries("S1", Color.Blue); + B1 = new TimeSeries("B1", Color.Blue); + + Draw(ssetup, 0); + Draw(bsetup, 0); + Draw(bbreak, 0); + Draw(sbreak, 0); + Draw(senter, 0); + Draw(benter, 0); + + Draw(S1, 2); + Draw(B1, 2); + } + + public override void OnBarOpen(Bar bar) + { + if (86400 == bar.Size)//当天最后一根K线 + { + i_reverse = reverse * (bar.Open / 100.0); + i_rangemin = rangemin * (bar.Open / 100.0); + div = Math.Max(xdiv, 1); + + base.ChangeTradingDay(); + } + } + + public override void OnBar(Bar bar) + { + if (86400 == bar.Size) + { + //表示今天结束了,要记下今天的开高底收和明天可以用到的价格 + UpdateAtDaily_RBreaker(bar); + UpdateAtDaily_HighLow(bar); + + rfilter = (preDayHigh - preDayLow) >= i_rangemin; + return; + } + + UpdateAtBar_RBreaker(bar); + UpdateAtBar_HighLow(bar); + + double _S1 = _senter + (HighToday - _ssetup) / div; + double _B1 = _benter - (_bsetup - LowToday) / div; + + S1.Add(bar.DateTime, _S1); + B1.Add(bar.DateTime, _B1); + + do + { + // 尾盘平仓 + if (0 != ExitOnClose(60,"")) + break; + + if (GetCurrentQty() > 0) + { + if ((HighToday > _ssetup && bar.Close < _S1) + || bar.Close < _sbreak) + { + string text = string.Format("{0}>{1}&&{2}<{3}", + HighToday, _ssetup, + bar.Close, _S1); + TargetPosition = -1; + TextParameter.Text = text; + } + } + else if (GetCurrentQty() < 0) + { + if ((LowToday < _bsetup && bar.Close > _B1) + || bar.Close > _bbreak) + { + string text = string.Format("{0}>{1}&&{2}<{3}", + LowToday, _bsetup, + bar.Close, _B1); + TargetPosition = 1; + TextParameter.Text = text; + } + } + else + { + if (bar.Close > _bbreak) + { + TargetPosition = 1; + TextParameter.Text = string.Format("{0}>{1}", bar.Close, _bbreak); + } + if (bar.Close < _sbreak) + { + TargetPosition = -1; + TextParameter.Text = string.Format("{0}<{1}", bar.Close, _bbreak); + } + } + + } while (false); + + base.OnBar(bar); + } + } + +} diff --git a/Demo/QuantBox.OQ.Demo/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/Demo/QuantBox.OQ.Demo/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000..a6eb8ce Binary files /dev/null and b/Demo/QuantBox.OQ.Demo/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.csproj.FileListAbsolute.txt b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..4ea073f --- /dev/null +++ b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.csproj.FileListAbsolute.txt @@ -0,0 +1,5 @@ +D:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Demo.dll +D:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\QuantBox.OQ.Demo.pdb +D:\用户目录\Documents\GitHub\OpenQuant\Demo\QuantBox.OQ.Demo\obj\Debug\QuantBox.OQ.Demo.csprojResolveAssemblyReference.cache +D:\用户目录\Documents\GitHub\OpenQuant\Demo\QuantBox.OQ.Demo\obj\Debug\QuantBox.OQ.Demo.dll +D:\用户目录\Documents\GitHub\OpenQuant\Demo\QuantBox.OQ.Demo\obj\Debug\QuantBox.OQ.Demo.pdb diff --git a/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.csprojResolveAssemblyReference.cache b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.csprojResolveAssemblyReference.cache new file mode 100644 index 0000000..e508d73 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.csprojResolveAssemblyReference.cache differ diff --git a/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.dll b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.dll new file mode 100644 index 0000000..cd673c1 Binary files /dev/null and b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.dll differ diff --git a/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.pdb b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.pdb new file mode 100644 index 0000000..9531cbc Binary files /dev/null and b/Demo/QuantBox.OQ.Demo/obj/Debug/QuantBox.OQ.Demo.pdb differ diff --git a/Extensions/src/QunatBox.OQ.Extensions/QuantBox.OQ.Extensions.csproj b/Extensions/src/QunatBox.OQ.Extensions/QuantBox.OQ.Extensions.csproj index eda7b9d..ee59040 100644 --- a/Extensions/src/QunatBox.OQ.Extensions/QuantBox.OQ.Extensions.csproj +++ b/Extensions/src/QunatBox.OQ.Extensions/QuantBox.OQ.Extensions.csproj @@ -16,7 +16,7 @@ true full false - ..\..\..\..\..\..\..\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Bin\ + C:\Program Files %28x86%29\SmartQuant Ltd\OpenQuant\Bin\ DEBUG;TRACE prompt 4 @@ -30,6 +30,7 @@ 4 + False ..\..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Bin\Newtonsoft.Json.dll @@ -40,24 +41,24 @@ False - ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Data.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Data.dll False False - ..\..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Execution.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Execution.dll False - ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.FIX.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.FIX.dll False - ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Instruments.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Instruments.dll False - ..\..\..\..\..\..\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Providers.dll + C:\Program Files (x86)\SmartQuant Ltd\OpenQuant\Framework\bin\SmartQuant.Providers.dll False @@ -91,6 +92,9 @@ + + + + \ No newline at end of file