您的位置:首页 > 其它

如何写自己的交易策略

2018-06-09 21:43 113 查看

基本概念:

开始实践:

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);

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: