如何写自己的交易策略
基本概念:
开始实践:
1. 写一个指标
2. 我们有了一个MA指标,现在利用它来实现一个双均线交叉交易策略吧!
3. 怎样使用我们的策略呢?
应注意的问题:
1. 在实盘策略中,不要使用未来数据
2. 在实盘状态下,与未连接行情的模拟状态会有所不同:
3. ValueSeries 类的AddOrFlush()方法的错误用法: 如何写自己的交易策略 编写自己的交易策略需要一些c#知识,在此不多做介绍。List<T>等数据结构均可在策略中使用。
1. DateSeries(日期序列):
DateSeries 是一个日期类型的“数组”。
2. ValueSerie(值序列):
ValueSerie可以理解为:一个可绘制在窗口区的 double 类型的 “数组”。
值序列[0]表示序列中的倒数第一个值。
值序列[1]表示序列中的倒数第二个值。
……
值序列[n]表示序列中的倒数第 n + 1个值。
3. Indicator(指标):
Indicator是每收到一个行情数据时,都会按其实现逻辑自动计算的值序列。
4. ContractBarSeries(合约):
ContractBarSeries是包含 Open、High、Low、Close、Vol、OI值序列及合约信息的集合。
5. Strategy(策略):
Strategy 是每收到一个行情数据时,都会按其实现逻辑自动计算并发单的ContractBarSeries 的集合。
开始实践:
1.写一个指标
打开VS并新建一个项目—“类库(.NET Framework)”。选择“”菜单下的“配置管理”命令。在弹出的“配置管理器”对话框中,在“平台”的下拉列表框中选择“<新建...>”。那么“平台”下的选项会变为“x64”,单击“关闭”按钮关闭对话框。将“Base.dll”文件复制到程序目录中,并添加对其的引用。添加using TradePlat语句。
指标代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using TradePlat; namespace IndicatorLib{ ///<summary> ///计算简单移动平均 SMA,通过 R 属性返回计算结果 ///</summary> publicclassMA : Indicator { ///<summary> /// ///</summary> ///<paramname="strategy 指标所属的策略"></param> ///<paramname="str 输入序列的名称。如:“Close”、“High”等"></param> ///<paramname="p 计算周期"></param> public MA(ContractBarSeries contractBarSeries, string str) : base(contractBarSeries, str) { } public MA(ValueSeries vs) : base(vs) { } privateint _period; privateValueSeries _outSeries = newValueSeries(0); //输出系列 ///<summary> ///指标名--指标名 + 参数 ///</summary> publicoverridestring Name { get => "MA:" + Period; } ///<summary> ///指标计算周期--小于零则返回 0 ///</summary> publicint Period { get => _period; set { if (value < 0) { _period = 0; } else { _period = value; } } } //计算过程中使用的变量 double sum; //和 ///<summary> ///计算并更新指标 ///当指标计算参数或输入系列长度小于等于零时,返回包含零个元素的 ValueSeries(0) ///</summary> ///<param name="inBar"></param> publicoverridevoid UpData(bool inBar) { if (_period <= 0 || _inSeries.Length <= 0) { _outSeries = newValueSeries(0); } else { if (_inSeries.Length < _period) { _outSeries.AddOrFlush(double.NaN, inBar); } else { sum = 0; for (int i = 0; i < _period; i++) { sum += _inSeries[i]; } _outSeries.AddOrFlush(sum /_period, inBar); } } } ///<summary> ///返回输出系列 ///</summary> publicoverrideValueSeries R { get => _outSeries; } }
}
2. 我们有了一个MA指标,现在利用它来实现一个双均线交叉交易策略吧!
打开VS并新建一个项目—“类库(.NET Framework)”。选择“”菜单下的“配置管理”命令。在弹出的“配置管理器”对话框中,在“平台”的下拉列表框中选择“<新建...>”。那么“平台”下的选项会变为“x64”,单击“关闭”按钮关闭对话框。将“Base.dll”文件及上一步生成的“IndicatorLib.dll”文件复制到程序目录中,并添加对他们的引用。添加usingSystem.ComponentModel; 、using TradePlat;和using IndicatorLib;语句。
策略代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.IO;using System.ComponentModel;using TradePlat;using IndicatorLib; namespace StrategyLib{ ///<summary> /// ///</summary> publicclassTwoSma : Strategy { privateContractBarSeries _bs; privateMA ma; privateMA ma2; privateVolume vol; [CategoryAttribute("参数"), DescriptionAttribute("短周期-多少个Bar")] publicint Period1 { get => ma.Period; set { if (value < 0) { ma.Period = 0; } else { ma.Period = value; } } } [CategoryAttribute("参数"), DescriptionAttribute("长周期-多少个Bar")] publicint Period2 { get => ma2.Period; set { if (value < 0) { ma2.Period = 0; } else { ma2.Period = value; } } } ///<summary> /// ///</summary> ///<paramname="bs"></param> ///<paramname="str"></param> ///<paramname="p"></param> public TwoSma(ContractBarSeries[] bsArray) : base(bsArray) { if (bsArray != null && bsArray.Length > 0) { _bs = bsArray[0]; AddToCurrentWindow(_bs); ma = newMA(_bs, "Close"); AddToCurrentWindow(ma); //将指标 ma 添加到当前窗口区以显示 ma2 = newMA(_bs, "Close"); AddToCurrentWindow(ma2); //将指标 ma2 添加到当前窗口区以显示 //vol = newVolume(_bs); //vol.R.IsPillar = true; //以差状图形式绘制成交量 //AddToNewWindow(vol); //将指标 vol 添加到新的窗口区以显示 } } ///<summary> ///策略名称 ///</summary> publicoverridestring Name { get => this.GetType().ToString(); } publicoverridestring KeyName { get => _bs.InstrumentName; } ///<summary> ///策略参数的字符串表示 ///</summary> publicoverridestring ParameterString { get { return"Period1:" + Period1 + ", Period2:" + Period2 + ", " + base.ParameterString; } } ///<summary> ///返回序列--测试时用 ///</summary> [Browsable(false)] publicValueSeries Return { get => ma.R; } ///<summary> ///策略具体执行的内容 ///</summary> ///<paramname="inBar"></param> protectedoverridevoid Execute(bool inBar) { if (Period1 == 0 || Period2 == 0) { OnError("参数 Period 设置有误!"); } else { ma.UpDataIndicator(inBar); ma2.UpDataIndicator(inBar); if (_bs.NoHasLong && (ma.R[2]<= ma2.R[2] && ma.R[1] > ma2.R[1]))//上穿 { _bs.BuyToCover(_bs.Open[0],"s1", Lots); _bs.Buy(_bs.Open[0], "b1", Lots); } if (_bs.NoHasShort && (ma.R[2] >=ma2.R[2] && ma.R[1] < ma2.R[1]))//下穿 { _bs.Sell(_bs.Open[0], "b1", Lots); _bs.SellShort(_bs.Open[0], "s1", Lots); } } } //
}
3. 怎样使用我们的策略呢?
将“IndicatorLib.dll”文件复制到程序目录下,将“StrategyLib.dll”文件复制到程序目录下的“strategies”文件夹下。现在运行我们的程序就可以在程序中加载刚刚实现的策略了。
应注意的问题:
1. 在实盘策略中,不要使用未来数据
像 _bs.High[0]、_bs.Low[0] 这样的数据我们称为:未来数据,它们表示当前这根 Bar 的最高价、最低价。由于这根 Bar 并未结束,所以它的最高价、最低价仍在变化之中,尚不确定。
由于 _bs.Open[0] 在这根一出现时,便已确定。所以它不是未来数据。_bs.Close[0] 则代表这根 Bar 的最新价,所以它也不是未来数据。
2.在实盘状态下,与未连接行情的模拟状态会有所不同:
if (_bs.Close[0] >= BuyPosition[0]) //在实盘状态下表示最新价 >= BuyPosition[0]
{
……
}
if(_bs.Close[0] >= BuyPosition[0]) //在静态状态下表示收盘价 >= BuyPosition[0]
{
……
}
由于这种情况的存在,所以在接入实盘数据前要求输入目前实际持仓的信息。
3.ValueSeries 类的AddOrFlush()方法的错误用法:
阅读更多
val = (_mPeriod *_inSeries[0] + (_nPeriod - _mPeriod) * _outSeries[0]) / _nPeriod;
_outSeries.AddOrFlush(val,inBar);
错误的原因:指标每 tick 会运行一次,上面代码是用 _outSeries[0] 更新 _outSeries[0],得到是当前Bar 的累积值。
正确的写法:
if (!inBar)
{
_outSeries.Add(double.NaN);
}
val = (_mPeriod *_inSeries[0] + (_nPeriod - _mPeriod) * _outSeries[1]) / _nPeriod;
_outSeries.Flush(val);
- 有趣的密码加密策略,你知道自己的密码如何在网站中存储的吗?
- 每日一招:如何建立自己的选股策略?
- 如何在Apache服务器上建立自己站点的P3P策略
- 如何建立自己的交易系统
- 经纬财富:乐平如何建立自己的交易系统
- EF学习笔记28:如何实现自己的预先加载(Eager Loading)策略
- 如何构建自己的交易系统
- 如何构建自己的交易系统
- 如何快速实现自己的数字资产交易想法(1)
- 如何发布自己的.NET程序
- 如何在C#中自定义自己的异常
- 如何提高自己的编程能力
- 如何自己定制iOS框架(framework)
- 如何将自己的Java项目部署到外网
- 如何自己创建正则表达式
- 如何判断自己是更适合技术岗位还是更适合销售类的岗位
- [20161027读书笔记]如何构建自己的知识体系
- 如何在C#中加载自己编写的动态链接库(DLL)
- 如何利用C++ Builder 5.0 Enterprise 创建用户自己的网上聊天程序
- GCC:如何自己编写Makefile