Today's the day

向软件大牛炫耀我会焊单片机,向硬件大牛炫耀我会写 Rails,向软硬件大牛炫耀我生物,向软硬件生物大牛炫耀我会折腾期货 -_-bbb

暂时告别 .net 版的 Multicharts

去年 Multicharts 发布了 .net 版,第一时间就买了 License,本想给交易程序弄点好玩的功能,但是到最后还是没有时间搞,还是老样子用 Easylanguage 版本继续跑。

当初买 .net 版的原因还有一个,就是因为 Multicharts 的 License 只能同时运行一个,而我的自动交易又是放在 VPS 上的,这样如果在交易日我有什么想法想在本地测试一下,就非常麻烦。所以当时的想法就是,趁着 .net 版的发布,买一个专门用来本地测试。

结果这几个月最大的感受,就是 C# 实在是不适合拿来测试自己的想法,原因就是 ---- 写起来太累了。

再次粘贴一下同一个程序 Easylanguage 和 C# 版本的对比:

Easylanguage:

input: Price( High ), Length( 20 ) ;
 
Buy 1 share next bar at Highest( Price, Length ) + 1 point stop;

C#:

using System;
using PowerLanguage.Function;
 
namespace PowerLanguage.Strategy
{
    public class Channel_Breakout_LE : SignalObject
    {
        private ISeries<Double> m_price;
 
        private int m_length = 20;
 
        private HighestFC m_highestfc;
 
        private IOrderPriced m_Order;
 
        public Channel_Breakout_LE(object ctx) :
            base(ctx) {}
 
        private ISeries<Double> price{
            get { return m_price; }
        }
 
        [Input]
        public int length{
            get { return m_length; }
            set { m_length = value; }
        }
 
        protected override void Create(){
            m_highestfc = new HighestFC(this);
            m_Order = OrderCreator.Stop(new SOrderParameters(Contracts.Default, "ChBrkLE", EOrderAction.Buy));
        }
 
        protected override void StartCalc(){
            m_price = Bars.High;
            m_highestfc.pricevalue = price;
            m_highestfc.len = new Lambda<Int32>(delegate { return length; });
        }
 
 
        protected override void CalcBar(){
            m_Order.Send((m_highestfc[0]
                               + (1*Bars.Point)));
        }
    }
}

每次有个想法开始着手写 C# 版本的代码,等我把那些对象啊类啊初始化好,我都已经忘了想法是什么了……

想画一条线还得去新建个对象,然后初始化才能用,好麻烦啊。

再加上有些实用的 Easylanguage 函数并没有移植过来,还得自己重新写。

再加上因为代码增多造成的各种 bug,比如类型转换错误呐,声明错误呐……

总之用 C# 测试自己的想法就是个杯具。

 

于是只好用回 Easylanguage 版,但是又不想再去买第二个 License,也不放心用 .net 版去自动交易,所以一段时间以来测试都留在非交易日的周末去做,不过最近周末总是不在家,测试工作也就越来越懈怠。

上个周末反省了一下觉得这样不行,最后还是下定决心再买个 License,先去官方查了查购买第二个 License 有没有优惠政策,结果看到了这个:

真是相见恨晚,于是就这样把 .net 的 License 给转到 Easylanguage,这样问题就解决了,不过也就暂时跟 .net 版告别了,以后有时间再去做好玩的东西吧~

 

话说本文并不是黑 .net 版本的 Multicharts 哦,用起来还是很不错的,如果某一天需要用到一些底层功能或是第三方库,还是非 .net 莫属,只不过不适合拿来测试自己的想法而已。

推特的影响力

似乎好久没有发文章了,于是来口水一下,首先郁闷的是不知道 GFW 抽什么筋,博客又被墙了囧……

今天凌晨玩 PS3 玩到一半瞟了一眼外盘,就看到惊心动魄的一幕:

 

 

当时就心想难道又有炸弹爆炸了么,查了一下新闻发现果然如此,只不过万幸的是这次只是假消息。

纽约时间23日下午1:07(北京时间24日凌晨1:07),标准普尔500指数约上涨1%,至1578点。但此时美联社的Twitter账号却发文指出,白宫发生爆炸,奥巴马总统受伤。标准普尔500指数的涨幅几乎全部抹去,当地时间下午1:10,一度跌到1563.03 。美联社后来澄清,其Twitter账号遭到黑客入侵,并未发生爆炸案,指数在三分钟内反弹。标准普尔500指数收盘上涨1%,报1578.78点。

感叹推特现在已经有这么大的影响力了,一条消息就能让指数瞬杀 1% 呐~

还有就是感叹市场上真的什么事情都会发生,各种真假消息再加上交易者情绪上的反馈,最终的结果是谁也无法预测的。

两笔单也因此瞬间被 pia 到止损╮(╯▽╰)╭。

虽然这次瞬杀的程度比不上前两年那次的 flash crash,不过结果依然很让人震撼。

也许从某个角度说明市场已经比较脆弱了,但是明天的事谁又会知道呢~

从 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 也可以这样做的话,步骤如下:

  1. 声明一个 VariableSeries<T> 类型的变量,具体类型要看变量的用途(如果用来保存价格信息就用 double,如果来保存持仓信息就用 int)。
  2. 在 Create 函数中,对这个变量进行初始化。
  3. 在 StartCalc 函数中,设置变量的初始值。
  4. 然后就可以在 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 中就要麻烦一些,步骤如下:

  1. 首先为这个订单声明一个 IOrderPriced(如果是 market 单就是 IOrderMarket) 变量。
  2. 在 Create 函数中,为这个订单创建实例。
  3. 在 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 中要:

  1. 在 Create 函数中创建订单对象时,第一个参数要设置为 Contracts.UserSpecified,这样才可以指定手数。
  2. 在发送订单的 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 更新之后自动调用。

基本的框架编辑器会自动生成,你只需要在对应的地方声明变量,在对应的函数填入代码即可。