任何依赖关系都可以表示为许多变量的函数,就像任何报价一样。最初的价格是:
P=P(t)
换句话说,价格是时间的函数。无法为每一对货币或任何其他工具可靠地确定函数的形式,因为这将需要无限的时间。但是这种表示形式什么都给不了我们。然而,价格具有双重性质,因为它既有可预测的成分,也有随机成分。可预测的部分不是函数本身,而是它的一阶导数。将此函数表示为某些术语是没有意义的,因为它没有用于交易的目的。但如果我们考虑它的一阶导数,有以下几点:
P'(t)=Pa'(t)+Pu'(t)
在这里,第一项反映了可以用数学分析的方法进行分析的部分,第二项是不可预测的部分。根据这个公式,我们可以说不可能100%准确地预测运动的大小和方向。没有必要考虑最后一项是什么,因为我们无法确定它。但是我们可以判断第一项。考虑到值函数是离散的,我们不能应用微分运算,可以假设这个项可以用不同的形式表示。但是相反,我们可以取一段时间的平均导数“st”。当应用于价格时,这将是条形图的持续时间;当应用于报价点(tick)时,它是两个报价点之间的最短时间。
PaM(t)=(Pa(t)-Pa(t-st))/st - 一段固定时间内的平均价格变动(时间导数)
Ma(t)=Ma(P(t),P(t-st) + ... + P(t-N*st), D(t),D(t-st) + ... + D(t-N*st),U[1](),U[2](t) + ... + U[N](t) )
P(t[i]) - 旧的价格(柱形或者报价点数据)
D(t[i]) - 其他货币对的旧价格值
U[i](t) - 其他影响市场的未知或已知数值
Ma(t) - 给定时间点的PaM(t)值的数学期望
换言之,我们假设价格的可预测部分可能取决于之前的条形图或刻度,以及其他货币对的价格数据、其他交易所和世界事件的数据。不过,应该理解的是,就算是这部分价格也无法100%准确预测,我们只能计算出它的一些特征。这样的特征只能是一个概率或一个随机变量的参数,如数学上的期望值、方差、标准差等数量的概率论。用数学期望操作足以使交易有利可图。经过时间和仔细思考,我们可以得出这样的结论:不仅可以用这个逻辑来分析市场。问题是,价格的可预测部分是根据市场参与者的活动而发展的。我们可以抛弃各种市场参数,除了市场参与者自己创造的因素。当然,所有这些都会导致我们的分析方法的可靠性降低,但这大大简化了模型。在这里,“st”值越小,我们的公式描述市场就越准确。
VMa(t)=VMa(P(t),P(t-st) + ... + P(t-N*st))
VMa(t)=VBuy(t)-VSell(t)
VMa(t) - 总交易量
VBuy(t) - 未平仓的买入订单交易量
VSell(t) - 未平仓的卖出订单交易量
上述函数描述了当前所有未平仓买入和卖出头寸的交易量差异。这些仓位的一部分相互补偿,而其余仓位是独立的。由于仓位是开放的,它们象征着一段时间后关闭的承诺。我们都知道买会使价格上涨,卖会使价格下跌。唯一知道价格走向的方法是衡量未平仓的成交量,并估计这些仓位的方向,只考虑未平仓的市场订单。
市场的波动性实际上与这个简单的事实有关。这只是一个更普遍的头寸波动过程的特例,即多头和空头的行为。
在处理柱形时,也可以考虑到一个柱里面有4个价格,这可以给我们提供更好的公式。更多的数据意味着更准确的分析,这就是为什么必须考虑所有价格数据的原因。但是,我不喜欢计算每一个 tick,因为这样会使算法慢十倍。此外,不同经纪商的 tick 数据可能不同。相反,大多数经纪商的开盘价和收盘价几乎相同。让我们修改交易量函数以考虑所有价格数据:
VMa(t)=VMa(O(t),O(t-st) +...+ O(t-N*st) + C(t),C(t-st) + C(t-N*st),H(t),H(t-st)...H(t-N*st),L(t),L(t-st)...L(t-N*st))
我们可以给这个函数添加更多的变量,比如时间、一周中的几天、几个月和几周,但是这会产生很多与特定市场区域相关的函数,而我们的目的是确定一般的市场物理学。我们将知道它是不能被打破的,因此只要市场存在,它就可以被使用。这个公式的另一个优点是它的多货币性。
实际上,使用这种表示类型没有意义,因为我们需要确切地知道如何以及基于什么数据来构建这个函数。我们不能只写这个函数的形式并确定依赖关系。但是,这些表达式可以帮助我们初步了解如何进行分析,以及如何进行以下假设。任何一组逻辑条件最终都可以表示为这样一个函数。相反,函数本身可以转化为一组条件。我们用哪种形式并不重要,理解它才是重要的。任何算法都可以简化为一个公式。有时,将信号描述为条件或条件系统比构建超复杂函数更容易。另一个大问题是如何建立这样一个功能。
在一个真实的交易系统中,我们不能一次分析整个历史,而只能分析一段固定的时间。这种分析有4种可能的方法,我将为它们命名并解释:
公式法 (指标或者它们的函数)
模拟法
普通数学法
机器学习类型方法
第一个选项假设我们使用一个特定值或一组值。一个例子是一个指标或我们自己的公式。这种方法的优点是 MetaTrader 4/5 终端中提供了一个大型工具箱。此外,市场和网络上有许多基于流行市场理论的指标。这种方法的缺点是,在大多数情况下,我们无法根据指标的工作原理来理解。即使我们理解了,这种理解也没有任何价值。
在第二种选择中,我们不使用我们不了解的数据或没有用处的数据。相反,我们可以试着模拟市场上的订单,这样我们就知道我们的系统在某种程度上能够描述一个方向上有多少个空头头寸,另一个方向上有多少个空头头寸。这些信息可以产生必要的预测,从而从全局的角度对市场进行精确的描述。这是机器学习的唯一选择。
数学是指对一些基本规律的理解或对某些数学原理的知识,这些知识允许利用任何报价,而不管当前的市场情况如何。事实上,任何函数,包括离散函数,都具有某些可以利用的特性。当然,这里我们假设依赖不是混沌的(在我们的例子中,外汇不是混沌的,所以任何报价都可以被利用)。在下一篇文章中,我们将分析一个几乎人人都知道的原则,但是知道和能够使用是两码事。这种方法的优点是,如果我们成功地构建了一个系统,我们就不必担心它在未来的表现。
第四种方法是最先进的方法,因为机器学习可以充分利用任何数据。你的计算能力越强,分析的质量就越高。这种方法的缺点是,它无助于理解市场物理学。优点是方法简单,以最少的时间获得最高质量的结果。但这种方法不适用于本文。
关于模式
每天的交易意味着大量的术语,每一个都有不同的重要性水平。有些术语经常被使用,尽管不是所有的交易者都明白它们的真正目的。其中一个术语是模式。我将试着用数学的语言来解释它。模式总是与特定的时间段、特定的货币对和图表周期相关联。有些模式很强,这种模式可以是多币种的,也可以是全局性的。理想的模式是圣杯。有一些说明可以应用于任何模式:
一个公式或一组条件的存在,象征着模式
策略测试器中的最小测试值或演示或真实帐户上的效果值
根据所有货币对和图表期间的表现对模式进行分类
发现这种模式的历史时期
未来的时间间隔,在此期间模式保持有效
在第一个时间段之后的将来的第二个时间段,在此期间原始模式保留一些参数,或将其反转
如果你仔细阅读每个属性,你就会明白模式是一个公式或一组条件,它们最准确地描述了价格在选定时间间隔内的变动。一个模式可能是随机的,特别是如果在一个很短的时间内发现或者如果相关的系统产生了过于乐观的值。了解在短期内测试系统时,发现全局模式的机会往往为零,这一点非常重要。这与样本量有关,样本越小,结果的随机性越高。
我们已经确定了什么是模式,但是如何有效地使用模式呢?这完全取决于这种模式是如何被发现的和它的质量。如果我们不考虑利用计算能力的分析方法,那么我们就来分析。在我看来,分析无法与任何类型的机器分析竞争——即使是一个优秀的分析师团队也无法处理一台机器可以处理的数据。总之,寻找全局模式的过程需要计算能力。好吧,除了你亲眼看到明显的东西,理解它们的物理原理。
编写最简单的仓位模拟器
为了寻找全局模式,开发一个能够描述市场参与者情绪的专家顾问将是一件有趣的事情。为此,我决定尝试创建一个市场仓位的模拟器,仓位将在靠近市场边缘的价格柱中模拟。有必要假设市场参与者不同,他们订单的权重也不同。同时,应以简单的形式提出这一点,如果一个简单的原型能够取得利润,那么它的原理可以被进一步使用。
逻辑将有条件地分为3个单独的模拟和它们的任何可能的混合组合:
止损订单的模拟
限价订单的模拟
市场订单的模拟
任意可能的组合
下订单将采用以下逻辑:
这些网格是每个新柱的位置,旨在模拟部分市场参与者的情绪。旧订单网格的状态将根据图表上显示的新柱进行更新。这种方法不是很精确,但是每一订单模式的模拟会导致没完没了的计算。而且,我不太相信订单点(tick)。
相对交易量分布有两种类型,衰减和均匀分布,但仅限于止损和限价订单,市场订单是均匀分布的。如果从长远的角度来看,还可以扩大分布的类型。图示如下:
在这里,表示订单的线的长度与这个订单的交易量成比例。我认为这样的演示图对每个人来说都是简单易懂的。
在这种情况下,一切都可以使用面向对象的方法来完成。让我们从描述编号列表开始:
enum CLOSE_MODE// how to close orders { CLOSE_FAST,// fast CLOSE_QUALITY// wait for an opposite signal };enum WORK_MODE// operation mode { MODE_SIMPLE,// slow mode MODE_FAST// fast mode };enum ENUM_GRID_WEIGHT//weight fill type for limit and stop orders { WEIGHT_DECREASE,// with attenuation if moving from the price WEIGHT_SAME// the same for the entire grid };enum ENUM_STATUS_ORDER// statuses of orders or positions { STATUS_VIRTUAL,// stop or limit order STATUS_MARKET,// market order STATUS_ABORTED// canceled stop or limit order };
模拟器将在两种模式下工作,慢速和快速。慢模式主要用于启动阶段的分析,在启动阶段分析中,计算是在最接近市场烛形的前“n”个烛形中进行的。在快速模式下,只对新出现的烛形进行计算。但是,简单的方法是不够的。为了提高算法速度,还需要额外的功能。相当大的计算是在专家顾问初始化时执行的。但是我们只需要在每个烛形上更新一个新烛形的模拟。根据与当前市场价格(也就是每个柱的 Open[i]) 之间的距离,将有两种类型的数量分布,即限价和止损订单。这是因为止损和限价指令的网格在每个柱都打开,具有不同的分布和权重。一段时间后,止损和限价订单变成市场订单。如果在规定的时间内价格未达到要求的价格,止损和限价订单将被取消。
让我们开始从简单到复杂地构建这个模拟,逐渐地把所有的东西放在一起。首先,定义什么是订单:
struct Order// structure symbolizing a player's order { public: double WantedPrice;// desired open price int BarsExpirationOpen;// If the order remains for certain number of bars, the player can't wait any more and cancels the order int BarsExpirationClose;//If this is a market order and the player does not want to wait, he closes the position double UpPriceToClose;//The total upward price movement at which the player closes the order (points) double LowPriceToClose;//The total downward price movement at which the player closes the order double VolumeAlpha;// current volume equivalent [0...1] double VolumeStart;// starting volume equivalent [0...1] int IndexMarket;// the index of the bar on which the virtual market turned into market ENUM_STATUS_ORDER Status;// order status Order(ENUM_STATUS_ORDER S)// constructor that creates a certain order { Status=S; } };
参数不多,每个参数对一般算法都很重要。许多字段适用于任何订单,而其中一些字段仅适用于限价或止损订单。例如,期望价格是市场订单的开盘价,而它恰恰是限价和止损订单的期望价格。
上下收盘价作为止损水平。同时,我们假设网格订单不是完全的订单,这个订单包含了一大堆订单,而它们只是合并成一个订单,以一定的价格以一定的交易量打开。起始量和当前量的变量告诉我们在特定条的特定级别上订单有多重要。
起始交易量是订单设置时的交易量,当前交易量是事件进一步发展时的交易量,重要的是买卖订单数量的比例,而不是某些订单的利润,交易信号将基于这些考虑产生。当然,我们可以提出其他信号,但这需要一些其他的考虑。还要注意的是,订单达到一定水平时不会关闭,但关闭会在每个柱逐渐发生,以尽量模拟事件的真实发展。