用自制 Mini 键盘无限冰
大菠萝3发售了半年多了,一直玩得不亦乐乎。虽然争议多多,不过作为一款单机游戏可以让人玩这么久而且还在不断更新内容,已经相当厚道了~
这次不是要评论游戏内容,而是……
从 EasyLanguage 迁移到 MC .NET (三):常用 EasyLanguage 函数写法
常用 EasyLanguage 函数写法
了解了 MC .NET 策略的基本结构,与订单发送的方式之后,理论上就可以写自己想要的策略了,不过要想把原 EL 策略移植过来的话,还要知道 EL 函数在 MC .NET 移植过来的写法才行。
大部分原 EL 函数,都被 MC .NET 打包至类或接口中,名字基本上也没有大变化,在 MC .NET 帮助文件中搜索原函数名称,基本上都能找到大致结果,这里列举一些常用函数的移植写法。
取得图标 K 线信息
在 EL 中,可以通过 Open[x]、Close[x]、High[x]、Low[x] 取得当前或者前 x 根 K 线的价格信息,在 MC .NET 中,这些信息被打包到 Bars 接口中,对应的关系如下(比如取得前一根 K 线的信息):
EasyLanguage | MC .NET |
Open[1] | Bars.Open[1] |
Close[1] | Bars.Close[1] |
High[1] | Bars.High[1] |
Low[1] | Bars.Low[1] |
Time[1] | Bars.Time[1] |
Date[1] | Bars.Time[1].Date |
Volume[1] | Bars.Volume[1] |
在 EL 中,经常比较 Date[0] 和 Date[1] 来判断是否来到新的一天,那么在 MC .NET 中就要这样写:
if ( Bars.Time[0].Date != Bars.Time[1].Date ) { // new day }
交易品种信息
当前交易的品种信息,比如 Minmove、BigPointValue、PriceScale 等,也被打包到了 Bars.Info 中,对于的关系如下:
EasyLanguage | MC .NET |
MinMove | Bars.Info.MinMove |
PriceScale | Bars.Info.PriceScale |
BigPointValue | Bars.Info.BigPointValue |
持仓信息
当前持仓的信息,比如 MarketPosition 等函数,被打包到了 StrategyInfo 接口中,对应的关系如下:
EasyLanguage | MC .NET |
MarketPosition | StrategyInfo.MarketPosition |
CurrentContracts | Math.Abs( StrategyInfo.MarketPosition ) |
值得注意的是,在 EL 里 MarketPosition 只包含了 -1、0、1 的方向信息,但是在 MC .NET 中也包含了持仓数量,所以要想获得 EL 中 CurrentContracts 的结果只要简单的取 StrategyInfo.MarketPosition 的绝对值就行了。
自动平仓函数
EL 中的自动平仓函数也被 MC .NET 移植了过来,可以直接使用,方法名称稍微有点改变:
EasyLanguage | MC .NET |
setstoppostion | CurSpecOrdersMode = ESpecOrdersMode.PerPosition; |
setstopcontract | CurSpecOrdersMode = ESpecOrdersMode.PerContract; |
setstoploss(1234) | GenerateStopLoss(1234) |
setpercenttrailling(1234, 20) | GeneratePercentTrailing(1234, 20) |
profittarget(1234) | GenerateProfitTarget(1234) |
breakeven(1234) | GenerateBreakEven(1234) |
setexitonclose | GenerateExitOnClose() |
序列变量
在 EL 中,所有自定义的 Vars 变量,都可以通过 vars1[x] 的形式来引用 x 根 K 棒之前的值,如果要想在 MC .NET 也可以这样做的话,步骤如下:
- 声明一个 VariableSeries<T> 类型的变量,具体类型要看变量的用途(如果用来保存价格信息就用 double,如果来保存持仓信息就用 int)。
- 在 Create 函数中,对这个变量进行初始化。
- 在 StartCalc 函数中,设置变量的初始值。
- 然后就可以在 CalcBar 函数中按照 EL 的形式使用这个序列变量了,唯一的不同,在于给变量赋值的时候不能直接使用 var1 = x 而是要使用 var1.Value = x。
以 double 类型的序列变量为例:
namespace PowerLanguage.Strategy { public class test3 : SignalObject { public test3(object _ctx):base(_ctx){} private VariableSeries<double> var1; protected override void Create() { var1 = new VariableSeries<double>(this); } protected override void StartCalc() { var1.DefaultValue = 0; } protected override void CalcBar(){ var1.Value = Bars.Close[0]; if( var1[0] != var1[1] ) { //... } } } }
有了这些函数,基本上可以移植大部分 EL 策略了,迁移教程也告一段落。当然这并不是全部,更详细的信息可以参考 MC .NET 编辑器的帮助文件,或是直接在编辑器中查看类或者接口的自动补全,基本上就可以把用法了解个大概。当然更好的方法还是参考 MC .NET 内置策略代码的写法,不过官方说目前的内置策略代码有一部分是自动生成的,所以写法可能冗杂一些,并不一定要完全仿照内置策略的模式来写。
从 EasyLanguage 迁移到 MC .NET (二):发送订单
发送订单
在 MC .NET 中,发送买卖的订单要比 EL 中麻烦很多,最主要的区别在于,要事先为策略中所有可能会用到的订单建立订单对象,不同类型的订单(例如 Limit、Stop、Market)在创建订单对象的时候要指定不同的参数。
开仓
发送开仓订单在 EL 中的写法是这样的:
Buy next bar at 1200.5 limit; // Limit Order Buy next bar at 1234.5 stop; // Stop Order Buy next bar at market; // Market Order
在 MC .NET 中就要麻烦一些,步骤如下:
- 首先为这个订单声明一个 IOrderPriced(如果是 market 单就是 IOrderMarket) 变量。
- 在 Create 函数中,为这个订单创建实例。
- 在 CalcBar 函数中发送订单。
namespace PowerLanguage.Strategy { public class test2 : SignalObject { public test2(object _ctx):base(_ctx){} private IOrderPriced buy_limit_order; // Limit Order private IOrderPriced buy_stop_order; // Stop Order private IOrderMarket buy_market_order; // Market Order protected override void StartCalc() { } protected override void CalcBar(){ // ... buy_limit_order.Send(1200.5); buy_stop_order.Send(1234.5); buy_market_order.Send(); // ... } } }
平仓
平仓单在 EL 中的写法是这样的:
sell next bar at market; buytocover next bar at market;
在 MC .NET 中,平仓单和上面的开仓单的写法完全一样,区别只在于在 Create 函数中,把参数设置为 EOrderAction.Sell 或 EOrderAction.BuyToCover:
... protected override void Create() { // ... sell_order = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.Sell)); buytocover_order = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, EOrderAction.BuyToCover)); } ...
Limit 和 Stop 的平仓单同理。
指定手数
上面的例子并没有设置买卖的手数,所以默认买卖的手数为策略设置中的默认值,如果想要指定手数要怎么写呢?
在 EL 中,指定手数(比如买 5 手)的写法如下:
Buy 5 shares next bar at 1234.5 stop;
在 MC .NET 中要:
- 在 Create 函数中创建订单对象时,第一个参数要设置为 Contracts.UserSpecified,这样才可以指定手数。
- 在发送订单的 Send 函数中指定具体的手数。
... protected override void Create() { // ... buy_stop_order = OrderCreator.Stop(new SOrderParameters(Contracts.UserSpecified, EOrderAction.Buy)) } ... protected override void CalcBar(){ // ... buy_stop_order.Send(1234.5, 5); // ... }
从 EasyLanguage 迁移到 MC .NET (一):基本结构
Multicharts .NET 虽然已经正式发布了(以下简称 MC .NET),但是官方坦言说现在只能算是 public beta 的阶段,还是有一些 bugs,所以要想实盘交易还是再等等吧,正好趁这段时间把策略移植过来。
花了很长时间把原来的策略改写为 .NET 版本,官方的文档太少,可以参考的只有 help 文件和自带的例子,还好自己用的策略并不复杂,基本上都已经搞定,这里记录一下基本的迁移方法,如果你已经有现成的 EasyLanguage/PowerLanguage (以下简称 EL)策略,那么照着这个过程基本上可以把大致框架迁移过来。
注:这里的迁移主要指的是交易策略代码的迁移,也就是 Signal,至于 Indicator 和Function,和 Signal 大同小异,参照着来就可以了。
基本结构
在 EL 里,基本的策略代码结构像下面这样(once 的语法似乎只在 PowerLanguage 中才有):
Inputs: input1(0), input2(0); Vars: var1(0), var2(0); once begin // code executed only once end; // strategy code starts here ... //
而在 MC .NET 中,基本的结构像是这样:
namespace PowerLanguage.Strategy { public class Test1 : SignalObject { // Inputs: private int m_input1 = 0; [Input] public int Input1{ get { return m_input1; } set { m_input1 = value; } } // Vars: private int var1 = 0; private int var2 = 0; public Test1(object _ctx):base(_ctx){} // default constructor protected override void Create() { // create variable objects, function objects, order objects etc. // executed only once } protected override void StartCalc() { // code executed only once } protected override void CalcBar(){ // strategy code start here ... } } }
对应规则如下:
- 参数 Inputs 对应为 getter setter 属性,并在之前声明 [Input],这样才会被 MC 识别出来。
- 策略运行时的变量 Vars,直接声明成 private 变量。
- 默认生成的同名构建函数(第 16 行),无需改动。
-
基本的函数有三个:Create、StartCalc、CalcBar
- Create:在策略初始化之前调用,只执行一次,一般在这里初始化各种变量和对象。
- StartCalc:相当于 EL 的 once,在策略初始化之后只执行一次,一般在这里检查运行环境和设置变量的默认值。
- CalcBar:相当于 EL 的主程序代码,再每一个 bar/tick 更新之后自动调用。
基本的框架编辑器会自动生成,你只需要在对应的地方声明变量,在对应的函数填入代码即可。
也用上了传说中的光纤
年初就听说要进行光纤试点,几个月后看到有人都用上了,眼馋不已,不过心想自己的小区并不是新建的估计没戏了吧。
没想到上周竟然看到了光改申请通知,兴冲冲的去报名,一周过后工作人员入户装好,于是我也用上传说中的光纤。
虽然号称光纤入户,不过为了避免在室内拉明线,在入户前还是要转成电线之后从墙内通过暗孔拉电脑前,然后转成光纤再接入光纤猫,速度并没有什么损失,标称 20M 下载速度可以稳定在 2.6M/s 左右。
不过这只是渣雷最大的下载速度,普通的网页浏览和之前并没有感受到大的差别,视频缓冲的速度的确是翻了好几番。
可是在这之前大菠萝也下载过了,山狮也装过了,暂时还不知道拿来下载什么大的东西 ……