文章 "什么是趋势,行情结构是基于趋势还是横盘?" - 页 10

 

我明白你的问题所在了。一开始你说过程的最大偏差是 40,然后你就按 40 计算。但是这个过程有可能出现 "+"和"-",从而产生 81 个变量(精确为 0)。

您在 X 轴上绘制了以 2 为单位的 40 个聚类点。

这就是为什么会出现这样的图表。

我将数据从 Excel 转移到 MQL。

利用标准库的功能,我选择了西格玛参数来重复您从 Excel 中得到的图表,并以第 2 步强制分组。

结果发现,对于您的组合过程,MO 0 和 sigma 6.45 的正态分布过程是合适的。

//+------------------------------------------------------------------+
//|NormalSimple.mq5
//|https://www.mql5.com | |
//+------------------------------------------------------------------+
#include <Graphics\Graphic.mqh>
#include <Math\Stat\Normal.mqh>
#include <Math\Stat\Math.mqh>
#property script_show_inputs
//--- 输入参数
input double mean_value=0;  // 数学期望值(平均值)
input double std_dev=6.45;     // 标准偏差(标准偏差)
//+------------------------------------------------------------------+
//| 脚本程序启动功能|
//+------------------------------------------------------------------+
void OnStart()
  {
   double arrayTeoryX[41]= {-40,-38,-36,-34,-32,-30,-28,-26,-24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,0,
                            2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40
                           };
   double arrayTeoryY[41]= {0.00000009,3.63798 E-06,7.09406 E-05,0.000898581,0.008311872,0.059845479,0.349098627,
                            1.695621904,6.994440355,24.86912126,77.09427591,210.2571161,508.121364,1094.415245,
                            2110.657973,3658.473821,5716.365345,8070.162839,10311.87474,11940.06549,12537.06876,
                            11940.06549,10311.87474,8070.162839,5716.365345,3658.473821,2110.657973,1094.415245,
                            508.121364,210.2571161,77.09427591,24.86912126,6.994440355,1.695621904,0.349098627,
                            0.059845479,0.008311872,0.000898581,7.09406 E-05,3.63798 E-06,9.09495 E-08
                           };
//--- 禁用价格图表显示
   ChartSetInteger(0,CHART_SHOW,false);
//--- 初始化随机数生成器
   MathSrand(GetTickCount());
//--- 生成随机变量的样本
   long chart=0;
   string name="GraphicNormal";
   int n=100000;       // 样本中的数值个数
   int ncells=41;       // 直方图中的区间数
   double x[];          // 直方图区间中心
   double y[];          // 样本中属于区间的数值个数
   double data[];       // 随机值取样
   double max,min;      // 样本中的最大值和最小值
//--- 从正态分布中获取样本
   MathRandomNormal(mean_value,std_dev,n,data);
//--- 计算数据以构建直方图
   CalculateHistogramArray(data,x,y,max,min,ncells);
   /*
//--- 获取序列边界和步长以构建理论曲线
 double step;
 GetMaxMinStepValues(max,min,step);
 step=MathMin(step,(max-min)/ncells);
//--- 获取区间 [min,max] 上的理论计算数据
 double x2[];
 double y2[];
 MathSequence(min,max,step,x2);
 MathProbabilityDensityNormal(x2,mean_value,std_dev,false,y2);
//--- 缩放
 double theor_max=y2[ArrayMaximum(y2)];
 double sample_max=y[ArrayMaximum(y)];
 double k=sample_max/theor_max;
 */
   /*
 for(int i=0; i<ncells; i++)
 y[i]/=k;
 */
//--- 显示图表
   CGraphic graphic;
   if(ObjectFind(chart,name)<0)
      graphic.Create(chart,name,0,0,0,1000,680);
   else
      graphic.Attach(chart,name);
   graphic.BackgroundMain(StringFormat("Normal distribution mu=%G sigma=%G",mean_value,std_dev));
   graphic.BackgroundMainSize(16);
//--- 绘制所有曲线
   graphic.CurveAdd(x,y,CURVE_HISTOGRAM,"MQL step 2").HistogramWidth(6);
   graphic.CurveAdd(arrayTeoryX,arrayTeoryY,CURVE_LINES,"Excel");
//--- 现在我们来绘制理论分布密度曲线
//graphic.CurveAdd(x2,y2,CURVE_LINES, "理论");
//--- 绘制所有曲线
   graphic.CurvePlotAll();
   graphic.Update();
   double summ=0;
   for(int i=0; i<ArraySize(y); i++)
     {
      summ+=y[i];
     }
   Print("Y 的总金额" + summ);
  }
//+------------------------------------------------------------------+
//| 计算数据集的频率|
//+------------------------------------------------------------------+
bool CalculateHistogramArray(const double &data[],double &intervals[],double &frequency[],
                             double &maxv,double &minv,const int cells=10)
  {
   if(cells<=1)
      return (false);
   int size=ArraySize(data);
   if(size<cells*10)
      return (false);
   minv=data[ArrayMinimum(data)];
   maxv=data[ArrayMaximum(data)];
   double range=maxv-minv;
   double width=range/cells;
   width=2.0;
   minv=-41;
   if(width==0)
      return false;
   ArrayResize(intervals,cells);
   ArrayResize(frequency,cells);
//--- 设置区间的中心点
   for(int i=0; i<cells; i++)
     {
      intervals[i]=minv+(i+0.5)*width;
      frequency[i]=0;
     }
//--- 填入间隔频率
   for(int i=0; i<size; i++)
     {
      int ind=int((data[i]-minv)/width);
      if(ind>=cells)
         ind=cells-1;
      frequency[ind]++;
     }
   return (true);
  }
  /*
//+------------------------------------------------------------------+
//| 计算序列生成值|
//+------------------------------------------------------------------+
void GetMaxMinStepValues(double & maxv,double &minv,double &stepv) ------------------------------------------------------------------ { //--- 计算序列的绝对范围,得到正常序列。maxv,double &minv,double &stepv)
 {
//--- 计算序列的绝对范围以获得归一化精度
 double range=MathAbs(maxv-minv);
 int degree=(int)MathRound(MathLog10(range));
//--- 归一化 max.和 min.
 maxv=NormalizeDouble(maxv,degree);
 minv=NormalizeDouble(minv,degree);
//--- 我们还设置了从给定精度生成序列的步长
 stepv=NormalizeDouble(MathPow(10,-degree),degree);
 if((maxv-minv)/stepv<10)
 stepv/=10.;
 }
//+------------------------------------------------------------------+
*/
 
Alexey Klenov:

我明白你的问题所在了。起初,你说流程的最大偏差为 40,并按 40 计算。但是,这个过程既可以+,也可以-,所以你最终得到了 81 种变化(精确为 0)。

你在 X 轴上绘制了以 2 为增量的 40 个点。

这就是为什么会有这样一张图。

我将数据从 Excel 转移到了 MQL。

利用标准库的功能,我选择了西格玛参数,从 Excel 中复制了您的图表,并将步骤 2 强制分组。

结果发现,对于您的组合过程,MO 0 和 sigma 6.45 的正态分布过程是合适的。

哦,这就有意思了。是的,范围是-40...0...40,步长为 2,你写得都对。也许我在文章中没有把这一点写清楚。谢谢你的代码。
 

下午好

蓝色柱状图重复了您的实验,只是使用了 365 天的 GBPUSD tick 数据。

Renko 值为 0.0002 点,以 40 个 Renko 条为单位切分。

几乎完全重复了您在 excel 中的理论曲线。

因此,您在文章中提供的图 7 不可行。

 

代码如下

我正在查找错误,还没有发现任何错误。

//+------------------------------------------------------------------+
//|项目名称
//|Copyright 2020, CompanyName ||
//|http://www.companyname.net |
//+------------------------------------------------------------------+
#include <Graphics\Graphic.mqh>
#include <Math\Stat\Normal.mqh>
#include <Math\Stat\Math.mqh>
#property script_show_inputs
//--- 输入参数
//input double mean_value=0; // 数学期望值(平均值)
//input double std_dev=1; // standard deviation(标准偏差)
input double stepRenko=0.0002;   // Renko 柱的间距
//+------------------------------------------------------------------+
//| 脚本程序启动功能|
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 禁用价格图表显示
   ChartSetInteger(0,CHART_SHOW,false);
//--- 初始化随机数生成器
   MathSrand(GetTickCount());
//--- 生成随机变量的样本
   long chart=0;
   string name="GraphicNormal";
   int ncells=41;       // 直方图中的区间数
   double x[];          // 直方图区间中心
   double y[];          // 样本中属于区间的数值个数
   double data[];       // 随机值取样
   double max,min;      // 样本中的最大值和最小值

   MqlTick realTick[];
   ulong start=iTime(_Symbol,PERIOD_D1,365)*1000;         // 以毫秒为单位
   ulong finish=iTime(_Symbol,PERIOD_D1,1)*1000;         // 以毫秒为单位

   int countCopy=CopyTicksRange(_Symbol,realTick,COPY_TICKS_INFO,start,finish);
   Print("countCopy="+IntegerToString(countCopy));
   Print("0 tick time ="+TimeToString(realTick[0].time));
   Print("end tick time ="+TimeToString(realTick[countCopy-1].time));
   
   int index=0;
   double actualStep[];       // 用于 renko bars 的数组
   ArrayResize(actualStep,countCopy);
   ArrayInitialize(actualStep,0);
   double priceForCheck= realTick[0].bid;
   actualStep[0]=0;
   int cnt=0;

   for(int i=0; i<countCopy; i++)
     {
      if(realTick[i].bid>priceForCheck+stepRenko)
        {
         int add=(int)((realTick[i].bid-priceForCheck)/stepRenko);
         actualStep[index]+=add;
         priceForCheck+=stepRenko*(double)add;
         cnt+=add;
         if(cnt>39)
           {
            index++;
            cnt=0;
           }
         continue;
        }
      if(realTick[i].bid<priceForCheck-stepRenko)
        {
         int add=(int)((priceForCheck-realTick[i].bid)/stepRenko);
         actualStep[index]-=add;
         priceForCheck-=stepRenko*(double)add;
         cnt+=add;
         if(cnt>39)
           {
            index++;
            cnt=0;
           }
        }
     }
   ArrayResize(actualStep,index+1);
   Print("Count index="+IntegerToString(index));
   CalculateHistogramArrayItsMy(actualStep,x,y,max,min,ncells);

// 数据来自 Excel
   double arrayTeoryX[41]= {-40,-38,-36,-34,-32,-30,-28,-26,-24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,0,
                            2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40
                           };
   double arrayTeoryY[41]= {0.00000009,3.63798 E-06,7.09406 E-05,0.000898581,0.008311872,0.059845479,0.349098627,
                            1.695621904,6.994440355,24.86912126,77.09427591,210.2571161,508.121364,1094.415245,
                            2110.657973,3658.473821,5716.365345,8070.162839,10311.87474,11940.06549,12537.06876,
                            11940.06549,10311.87474,8070.162839,5716.365345,3658.473821,2110.657973,1094.415245,
                            508.121364,210.2571161,77.09427591,24.86912126,6.994440355,1.695621904,0.349098627,
                            0.059845479,0.008311872,0.000898581,7.09406 E-05,3.63798 E-06,9.09495 E-08
                           };
   // 将理论曲线缩放为实际曲线 
   double div=100000/index;
   for(int i=0; i<ArraySize(arrayTeoryY); i++)
     {
      arrayTeoryY[i]/=div;
     }

   CGraphic graphic;
   if(ObjectFind(chart,name)<0)
      graphic.Create(chart,name,0,0,0,1080,580);
   else
      graphic.Attach(chart,name);
//graphic.BackgroundMain(StringFormat("Normal distribution mu=%G sigma=%G stepRenko=%G",mean_value,std_dev,stepRenko));
//graphic.BackgroundMain(StringFormat("Normal distribution mu=%G sigma=%G",mean_value,std_dev));
   graphic.BackgroundMainSize(16);
//--- 绘制所有曲线
   graphic.CurveAdd(x,y,CURVE_HISTOGRAM,"Sample").HistogramWidth(6);
   graphic.CurveAdd(arrayTeoryX,arrayTeoryY,CURVE_LINES,"Excel");


//--- 绘制所有曲线
   graphic.CurvePlotAll();
   graphic.Update();
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool CalculateHistogramArrayItsMy(const double &data[],double &intervals[],double &frequency[],
                                  double &maxv,double &minv,const int cells=10)
  {
   minv=data[ArrayMinimum(data)];
   maxv=data[ArrayMaximum(data)];
   int range=maxv-minv;
   ArrayResize(intervals,range+1);
   ArrayResize(frequency,range+1);
   for(int i=0; i<range+1; i++)
     {
      intervals[i]=minv+i;
     }
   for(int i=0; i<ArraySize(data); i++)
     {
      int ii=(MathAbs(minv)+data[i]);
      //frequency[ii]+=MathAbs(data[i]);
      frequency[ii]+=1.0;
     }
   return (true);
  }
//+------------------------------------------------------------------+
 
Alexey Klenov:

下午好

蓝色柱状图重复了您的实验,只是使用了 365 天的英镑兑美元跳动数据

Renko 值为 0.0002 点,切割了 40 个 Renko 柱。

几乎完全重复了您在 excel 中的理论曲线。

因此,您文章中的图 7 不可行。

我使用分钟蜡烛图进行分析,当你将蜡烛图切成太小的块时,就会产生一些误差。
我没有 renko bars,算法有点不同。在 Renko 柱状图中,需要 2 个点才能形成一个反转块,但在我这里总是 1 倍。
请给我发一份刻度线历史记录,我下周会试试,然后给你看看我的结果。关于刻度线的想法应该略显新潮,但事实上,刻度线是不同的,这取决于来源。例如,有些模拟账户上的刻度点过多,这会导致反转过程。
 
Maxim Romanov:
我使用分钟蜡烛图进行分析,如果将蜡烛图切成太小的块,就会产生一些误差。
我没有 Renko bars,算法有点不同。使用 Renko bars 时,需要 2 个点才能形成一个反转块,而我总是 1 个点。
请给我发一份刻度线历史记录,我下周会试试,然后给你看看我的结果。关于刻度线的想法应该略显新潮,但事实上,刻度线是不同的,这取决于来源。例如,有些模拟账户上的刻度点过多,这会导致反转过程。

终端自行下载勾选历史记录(MT5、Alpari-MT5 服务器)。

变体。在终端中按住 Ctrl +U 键,然后在 ticks 选项卡上进行所有操作。

 
股票分布的正态性显然取决于观测值的数量:观测值越多,正态性越强。您应该比较相同的样本量。
 
Kristian Kafarov:
股票分布的正态性显然取决于观测值的数量:观测值越多,正态性越强。您应该比较相似的样本量。

从文章给出的例子来看,似乎确实如此。但实际上,并不存在这种影响。样本越多,结果越准确,但分布并不接近正态分布(尽管在研究中需要满足某些条件)。分布的性质更多地取决于交易工具,每种工具都略有不同。

 
这是一种分析平缓趋势的有趣方法。但我认为在实践中不太容易接受。相反,这些材料可以归结为对另一个方面的熟悉,仅此而已。
 
非常感谢你对市场的洞察和解释