美文网首页
码农的外汇之路[未完待续]

码农的外汇之路[未完待续]

作者: Perebor | 来源:发表于2017-02-10 11:45 被阅读1070次

    引子

    我是一个码农,一个程序员,一个开发者。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线组合

    中继组合

    上升三法

    下降三法

    反转组合

    早晨之星、黄昏之星

    穿头破脚(吞噬组合)

    相关文章

      网友评论

          本文标题:码农的外汇之路[未完待续]

          本文链接:https://www.haomeiwen.com/subject/yxfvsttx.html