码农的外汇之路[未完待续]
2019-12-09 10:33:44   来源:简书   评论:0 点击:

引子

我是一个码农,一个程序员,一个开发者。1998年上大学,计算机科学与技术专业,毕业后一直工作在软件开发行业一线。十几年之后的2016年,阴差阳错开始接触外汇交易行业,尝试使用码农的方法开始追求财务自由。

市场上几乎所有的外汇交易书籍都会强调“交易系统”的重要性。想实现稳定收益,必须要遵守交易纪律,完全按照事先制定好的交易系统执行。在交易中不要思考,不能临时改变主意,越是机械,越是死板越好。但是建立这个“系统”却需要交易者常年累月的经验积累和对系统的不停改进。我是外行,没有经验;也没有那么多时间和精力去操作1年以上的模拟盘来犯那些该犯得错误。而且,我现在还有一份全职的工作,没法每天看盘几个小时。所以,只能走另外的路径。

我用工具,我写程序,我把从别人书里学到的系统写成EA,跑历史数据验证。从验证中,我找到入市信号、途中头寸管理(加减仓)、出场点;学习、分析、理解各个系统原型的原理、优缺点,适应状况。

学习MT4和MQL4时,我参考了两本书。一本是 《MetaTrader4 外汇自动交易圣经》Dave C 王彤 刘斌 编著,中国经济出版社出版。另一本是《Expert Advisor Programming -- Creating Automated Trading Systems in MQL for MetaTrader 4》 Andrew R. Young , EDGEHILL PUBLISHING。
中文的那一本看起来很像是英文版的翻译和改编,目录章节都是基本一模一样。可能这也是作者特意表明 “编著”的原因。

关于MQL4 和 MQL5
从MQL4 build 600 之后,MetaQuest对MQL4做了巨大修改,(也许应该叫MQL4.5?)引入了很多MQL5的内容(Python3在一边看着,不说话),并且把MetaEditor也就是MQL的IDE进行了统一。
我上手晚,用的是MetaEditor version 5.0 build 1351, 04 Jul 2016。在实际中发现build 600之后的与上面书里中一些内容对不上号,比如那四个事件触发函数。本文全文使用的都是build600之后的版本,在2016年以后应该可以算是开箱可用。

MT4基本介绍

外汇散户使用最广泛的是MetaTrader4 软件平台。这个平台上有自己的MQL4语言来于系统交互,执行用户制定的逻辑判断、分析算法和交易动作。
MT4其实和各种“专业”软件很相似,如果你使用过工程软件(比如AutoCAD、IC Designer等等),并且为其写过扩展程序,就更容易掌握这种思想。这些软件都是在系统平台里集成了一门语言、解释器,依赖该语言的能力处理逻辑、计算以及文件读写、网络通信等通用功能,再把自己平台的功能细化并封装成各个函数“命令”供用户调用,给用户二次开发和实现复杂功能的能力。

MetaTrader4 是windows下的软件,在Mac OS X下使用PlayOnMac和Wine来模拟运行环境,已经很成熟,官方网站上有安装说明,可以放心使用。
MT4主要有几个模块:(可以再Menu View里打开和关闭)

  1. 导航栏 -- Navigator
  2. 图表窗口 -- Chart
  3. 数据窗口 -- Data Window
  4. 控制终端窗口 -- Terminal
  5. EA测试器 -- Strategy Tester

在开发时,用的最多的是 Navigator和 Tester, 很多时候基本不看其他窗口。

除此之外,还有一个MQL4的IDE -- MetaEditor。
和市场上的大部分IDE相同,MetaEditor也把屏幕切分成上有Menu和Toolbar,左有Navigator,中有Editor,下有Console(Toolbox)四部分。Editor支持语法高亮,自动补全等等功能。
MQL4是一门类似C的语言,或是说是一种扩展了的C语言,有基础的同行很容易上手。但是对于专业码农,这MQL却在空格缩进、变量、函数名大小写这种代码风格上很值得吐槽。我忍,谁叫这是为了赚钱做生意而不是追求码农的自我修养呢。

在Editor里编写完成EA程序后,需要compile成可执行文件,系统后缀为.ex4。屏幕下方Console里的Errors Tab会显示编译结果,有没有error或warning。之后就可以在MT4中使用这个EA了,不论是应用在图表交易上还是进行历史数据测试。

MT4 MQL 文件目录

作为约定MT4会把所有的开发EA相关文件放在它自己安装目录(以下用MT4_HOME代替)下的mql4目录下。如果你的EA有读写文件操作,请在MT4_HOME/tester/files下寻找。

MQL 文件类型

  • EA
    可以附在图表上进行,监听系统产生的Tick事件,被调用而进行交易。
  • Indicator 指标
    附在图标上,监听系统Tick,但是不能下单?TODO
  • Script
    一次性执行的脚本程序,由OnStart() 触发。
    再看看,还不会 TODO

MQL4 简单文件结构

  • 头部变量定义
    -- #property
    -- #include
    -- #input
    EA的各个输入参数,在MQL中是全局变量。在之前的版本中使用extern 关键字定义
  • 函数
    -- int OnInit() 构造函数?
    -- void OnTick() 事件循环?
    -- void OnDeinit() 析构函数?
    -- void OnTimer() 时间触发?
    -- double OnTester() Tester最后汇总用?
    -- void OnChartEvent() ?

-- void OnStart() 不是给EA用的,而是给一次性运行的script使用。

对于经验丰富的码农来说,这几个函数全是callback,或是说系统里定义好的interface,留给我们自己实现。对应的事件触发时,会执行相应的函数。

void OnStart() 函数

Script启动时调用,如果你的EA里含有这个函数,在新版的MT4中,会提示 “xx” is not expert and cannot be executed.

int OnInit() 函数

在程序初始时执行,可以进行全局变量的初始化等动作。在老版本的MQL4中,函数名为 int init(),现在为了和MQL5兼容,把几个主要函数名都加入了On打头。
下面例子里显示了一些市场信息内部变量,这是我们的交易中都必须使用的,具体会在后面介绍。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetTimer(60);
   Print("Balance: ",AccountBalance());
   Print("Equity: ",AccountEquity());
   Print("TickValue: ",MarketInfo(Symbol(),MODE_TICKVALUE));
   Print("Lot Size: ",GetSize());

   Print("MINLOT: ",MarketInfo(Symbol(),MODE_MINLOT));
   Print("MAXLOT: ",MarketInfo(Symbol(),MODE_MAXLOT));
   
   Print("Symbol name of the current chart=",_Symbol);
   Print("Timeframe of the current chart=",_Period);
   Print("The latest known seller's price (ask price) for the current symbol=",Ask);
   Print("The latest known buyer's price (bid price) of the current symbol=",Bid);
   Print("Number of decimal places=",Digits);
   Print("Number of decimal places=",_Digits);
   Print("Size of the current symbol point in the quote currency=",_Point);
   Print("Size of the current symbol point in the quote currency=",Point);
   Print("Number of bars in the current chart=",Bars);
   Print("Open price of the current bar of the current chart=",Open[0]);
   Print("Close price of the current bar of the current chart=",Close[0]);
   Print("High price of the current bar of the current chart=",High[0]);
   Print("Low price of the current bar of the current chart=",Low[0]);
   Print("Time of the current bar of the current chart=",Time[0]);
   Print("Tick volume of the current bar of the current chart=",Volume[0]);
   Print("Last error code=",_LastError);
   Print("Random seed=",_RandomSeed);
   Print("Stop flag=",_StopFlag);
   Print("Uninitialization reason code=",_UninitReason);
//---
   return(INIT_SUCCEEDED);
  }

	

void OnTick()

这是MT4 事件循环触发的最主要函数,市场中的每个Tick事件,都会触发该函数。我们的所有市场交易逻辑都在该函数中执行。
基本上的逻辑是,每个Tick时,相应的市场信息比如Bid,Ask,过去的bar数据,各种指标都会有相应更新。我们的逻辑会按照“交易系统”的逻辑去分析现在市场情况,分析自己持仓情况,做出下列决定:1)买n手;2)卖n手;3)修改头寸的Stop、Limit价;4)不动。
这里需要注意的是,每个Tick的时间很短,一个tick之后马上就是下一个tick。我们的函数运行时间有很严格的限制,如果运行过慢,在下一个tick进来的时候还没有结束,会出现跳过该tick的后果。
对于单张图表,MT4“看起来”是串行工作。处理完OnTick后,才会触发下一个Tick。

这种串行工作方式乍看起来会损失很多精度,但是从模拟人类的角度看起来也没什么问题。只要不是高频交易,这点时间比起人类的判断反应时间上要快的多。只是不能对相邻两个Tick做假设,因为它们的时间间隔是不固定,不保证的。

对于多个图表上同时运行的EA,很遗憾他们也是非并行运行。而是轮换的方法抢夺运行时的权限。

最好把OnTick函数想象成HTTP的stateless 模型。每次只从DB中拿出状态变量,重新判断局势然后做出反应。

void OnDeinit()

这个函数是EA结束时被执行,可以近似成析构函数,进行内存释放、关闭文件句柄等clean up 任务。

识别市场情况

一个系统主要由三部分组成,入市,头寸,出场。在市场的每个Tick到来时,都要首先分析市场的现状。在手工分析和交易时,交易者会把主要精力放到观察图表上,根据图表形状,技术指标来确定交易行为。

对于一个自动化交易的EA,第一步也是要取得市场上的所有信息,MQL4提供了MaketInfo()函数和一组预定义内部变量供我们使用。

MarketInfo()

double MarketInfo(string symbol, int type)

	

type 包括

MODE_POINT
MODE_DIGITS
MODE_SPREAD
MODE_STOPLEVEL
MODE_BID
MODE_ASK
MODE_LOW
MODE_HIGH
MODE_TIME
MODE_TICKSIZE
MODE_TICKVALUE
MODE_EXPIRATION
MODE_FREEZELEVEL

MODE_STARTING
MODE_STOPLEVEL
MODE_SWAPLONG
MODE_SWAPSHORT
MODE_SWAPTYPE

MODE_LOTSIZE
MODE_LOTSTEP
MODE_MAXLOT
MODE_MINLOT
MODE_CLOSEBY_ALLOWED

	

写个函数把它们都打出来看看

void report_marketinfo()
  {
   Print("START");
   Print(MarketInfo(_Symbol,MODE_ASK)); // ask
   Print(MarketInfo(_Symbol,MODE_BID)); // bid
   Print(MarketInfo(_Symbol,MODE_CLOSEBY_ALLOWED)); // 0
   Print(MarketInfo(_Symbol,MODE_DIGITS)); // 3 for USDJPY
   Print(MarketInfo(_Symbol,MODE_EXPIRATION)); // 0
   Print(MarketInfo(_Symbol,MODE_FREEZELEVEL)); // 0
   Print(MarketInfo(_Symbol,MODE_HIGH)); // 0
   Print(MarketInfo(_Symbol,MODE_LOTSIZE)); // 100000
   Print(MarketInfo(_Symbol,MODE_LOTSTEP)); // 0.1
   Print(MarketInfo(_Symbol,MODE_LOW)); // 0
   Print(MarketInfo(_Symbol,MODE_MARGINCALCMODE)); // 0
   Print(MarketInfo(_Symbol,MODE_MARGINHEDGED)); // 10000
   Print(MarketInfo(_Symbol,MODE_MARGININIT)); // 0
   Print(MarketInfo(_Symbol,MODE_MARGINMAINTENANCE)); //0
   Print(MarketInfo(_Symbol,MODE_MARGINREQUIRED)); // 1553.84
   Print(MarketInfo(_Symbol,MODE_MAXLOT)); // 50
   Print(MarketInfo(_Symbol,MODE_MINLOT)); // 0.1
   Print(MarketInfo(_Symbol,MODE_POINT)); // 0.001
   Print(MarketInfo(_Symbol,MODE_PROFITCALCMODE)); // 1
   Print(MarketInfo(_Symbol,MODE_SPREAD)); // 7
   Print(MarketInfo(_Symbol,MODE_STARTING)); // 0
   Print(MarketInfo(_Symbol,MODE_SWAPLONG)); // 0
   Print(MarketInfo(_Symbol,MODE_SWAPSHORT)); // 0
   Print(MarketInfo(_Symbol,MODE_SWAPTYPE)); // 0
   Print(MarketInfo(_Symbol,MODE_TICKSIZE)); // 0.001
   Print(MarketInfo(_Symbol,MODE_TICKVALUE)); // 0.9980836
   Print(MarketInfo(_Symbol,MODE_TIME)); // looks like cpu time, in 
   Print(MarketInfo(_Symbol,MODE_TIME)); // 1470182399 system epoch time, in second, use http://www.epochconverter.com/ to convert
   Print("END PRINT");
//
  }

	

预定义变量

https://docs.mql4.com/cn/predefined
_Digits
_Point
_LastError
_Period
_RandomSeed
_StopFlag
_Symbol
_UninitReason
Ask
Bars
Bid
Close (array)
Digits
High (array)
Low (array)
Open (array)
Point
Time (array)
Volume (array)

其他函数

AccountBalance()
AccountEquity()

如何使用MQL4分析现在的图形

识别单根K线

在交易上我是纯外行,对K线战法只有书本上的认识。下面争取用MQL来识别《外汇交易实战全典》书中提到的几种K线形态。

正常性

大阴线、阳线 (光头光脚)

OCHL

纺锤线(阴线阳线)

十字星

螺旋桨 (宝剑形)

反转形

锤子线、上吊线

倒锤子线、流星线

识别K线组合

中继组合

上升三法

下降三法

反转组合

早晨之星、黄昏之星

穿头破脚(吞噬组合)

 
 
7人点赞
 
外汇
 
 
 


作者:Perebor
链接:https://www.jianshu.com/p/885c921061ba
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关热词搜索:

上一篇:第一页
下一篇:最后一页

分享到: 收藏
评论排行