用于 Renko 制图的指标·进阶篇
🧱

用于 Renko 制图的指标·进阶篇

(2/3)· 从收盘价比较到箱体尺寸设定,手把手拆解 Renko 砖块生成的代码骨架

含代码示例 第 2/3 篇
很多人把 Renko 当成普通蜡烛的滤镜,结果砖块错位还怪数据源。其实它完全抛弃时间轴,只按固定箱体比较前一块砖的极值。先理清绘制顺序,再写代码才不会反复重绘。

「砖形图与ZigZag的绘制参数入口」

在 MT5 自定义指标里,砖形(Renko 类方块)和 ZigZag 的视觉呈现完全由一组 input 变量控制。把 shadow_print 设为 true,会在主图叠加影线阴影;filter_number 默认 0,代表反转所需砖块数走内置逻辑,调成 3 或 5 会明显改变砖形翻转密度。 ZigZag 部分有独立开关:zig_zag 控制主图是否画折线,zig_zag_shadow 决定高低点是否落在真实价格极值上。线宽 zig_zag_width 给 2,上行色 clrBlue、下行色 clrRed,肉眼区分趋势段够用。 square_draw 为 true 时主图才渲染砖块,square_fill 控制实心填充,square_width 与 frame_width 都默认 2 像素。frame_draw 管砖框,frame_color_up 用 clrBlue——这些参数直接决定你盯盘时图形是清爽还是拥挤。 外汇与贵金属波动剧烈,这类可视化仅辅助判势,实际反转概率随品种与周期漂移,请先在策略测试器用历史数据验证再上实盘。

MQL5 / C++
input class="type">bool      shadow_print=true;             class=class="str">"cmt">// Show shadows
input class="type">int       filter_number=class="num">0;              class=class="str">"cmt">// Bricks number needed to reversal
input class="type">bool      zig_zag=true;                 class=class="str">"cmt">// Whether ZigZag should be drawn on the main chart
input class="type">bool      zig_zag_shadow=true;          class=class="str">"cmt">// Draw ZigZag at highs and lows of the price
input class="type">int       zig_zag_width=class="num">2;              class=class="str">"cmt">// ZigZag line width
input class="type">color     zig_zag_color_up=clrBlue;     class=class="str">"cmt">// ZigZag up line class="type">color
input class="type">color     zig_zag_color_down=clrRed;    class=class="str">"cmt">// ZigZag down line class="type">color
input class="type">bool      square_draw=true;             class=class="str">"cmt">// Whether bricks should be drawn on the main chart
input class="type">color     square_color_up=clrBlue;      class=class="str">"cmt">// Up brick class="type">color on the main chart
input class="type">color     square_color_down=clrRed;     class=class="str">"cmt">// Down brick class="type">color on the main chart
input class="type">bool      square_fill=true;             class=class="str">"cmt">// Brick filling on the main chart
input class="type">int       square_width=class="num">2;               class=class="str">"cmt">// Brick line width on the main chart
input class="type">bool      frame_draw=true;              class=class="str">"cmt">// Whether to draw frames of the bricks
input class="type">int       frame_width=class="num">2;                class=class="str">"cmt">// Brick frame line width
input class="type">color     frame_color_up=clrBlue;       class=class="str">"cmt">// Up brick frames class="type">color

◍ 砖型图的缓冲与变量怎么铺

在 MT5 里手搓 Renko(砖型)指标,第一步是把各类数组先声明清楚。原文用 input color 控制下跌砖边框为 clrRed,其余上涨/下跌砖色由 RENKO_color 缓冲区分,这种分离让你在肉眼复盘时一眼能分出多空倾向。 核心数据走五个 INDICATOR_DATA 缓冲:RENKO_open / high / low / close / color,全部用 ArraySetAsSeries(...,true) 改成时间序列排列,最新砖在索引 0。辅助计算缓冲(Price、Date、Price_high、Price_low 等)标为 INDICATOR_CALCULATIONS,不参与绘图,只供 OnCalculate 内部搬运裸 K 数据。 全局变量里 obj 记图形对象数、a 计砖块数、bars 存柱数,date_start / date_stop / date_change 配合处理跨周期时间跳变。外汇与贵金属波动剧烈,砖型参数设错可能让历史回看完全失真,上机前先开策略测试器用 2023 年 EURUSD M5 跑一遍验证缓冲映射。 下面这段是 OnInit 里缓冲绑定的最小可运行片段,注意索引号与缓冲类型必须一一对应,漏掉 INDICATOR_COLOR_INDEX 会导致砖色不渲染。

MQL5 / C++
input class="type">color frame_color_down=clrRed; class=class="str">"cmt">// Down brick frames class="type">color
class=class="str">"cmt">//--- indicator buffers
class="type">class="kw">double RENKO_open[];
class="type">class="kw">double RENKO_high[];
class="type">class="kw">double RENKO_low[];
class="type">class="kw">double RENKO_close[];
class="type">class="kw">double RENKO_color[];
class="type">class="kw">double Price[]; class=class="str">"cmt">// copy price data to the buffer
class="type">class="kw">double Date[]; class=class="str">"cmt">// copy data to the buffer
class="type">class="kw">double Price_high[]; class=class="str">"cmt">// copy high prices to the buffer
class="type">class="kw">double Price_low[]; class=class="str">"cmt">// copy low prices to the buffer
class=class="str">"cmt">//--- calculation buffer arrays
class="type">class="kw">double up_price[]; class=class="str">"cmt">// up brick price
class="type">class="kw">double down_price[]; class=class="str">"cmt">// down brick price
class="type">char type_box[]; class=class="str">"cmt">// brick type(up, down)
class="type">class="kw">datetime time_box[]; class=class="str">"cmt">// brick copy time
class="type">class="kw">double shadow_up[]; class=class="str">"cmt">// up high price
class="type">class="kw">double shadow_down[]; class=class="str">"cmt">// down low price
class="type">int number_id[]; class=class="str">"cmt">// Index of Price_high and Price_low arrays
class=class="str">"cmt">//--- calculation global variables
class="type">int obj=class="num">0; class=class="str">"cmt">//variable for storing number of graphics objects
class="type">int a=class="num">0; class=class="str">"cmt">// variable to count bricks
class="type">int bars; class=class="str">"cmt">// number of bars
class="type">class="kw">datetime date_stop; class=class="str">"cmt">// current data
class="type">class="kw">datetime date_start; class=class="str">"cmt">// start date variable, for calculations
class="type">bool date_change; class=class="str">"cmt">// variable for storing details about time changes
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Custom indicator initialization function |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
 {
class=class="str">"cmt">//--- indicator buffers mapping
 SetIndexBuffer(class="num">0,RENKO_open,INDICATOR_DATA);
 ArraySetAsSeries(RENKO_open,true);
 SetIndexBuffer(class="num">1,RENKO_high,INDICATOR_DATA);
 ArraySetAsSeries(RENKO_high,true);
 SetIndexBuffer(class="num">2,RENKO_low,INDICATOR_DATA);
 ArraySetAsSeries(RENKO_low,true);
 SetIndexBuffer(class="num">3,RENKO_close,INDICATOR_DATA);
 ArraySetAsSeries(RENKO_close,true);
 SetIndexBuffer(class="num">4,RENKO_color,INDICATOR_COLOR_INDEX);
 ArraySetAsSeries(RENKO_color,true);
class=class="str">"cmt">//---
 SetIndexBuffer(class="num">5,Price,INDICATOR_CALCULATIONS); class=class="str">"cmt">// initialize price buffer

缓冲绑定与起算日的自适应收缩

指标初始化阶段先把 6/7/8 号缓冲区分别绑给 Date、Price_high、Price_low,类型都设成 INDICATOR_CALCULATIONS,意味着这三组数组只参与内部运算、不直接往图表上画。PlotIndexSetInteger(0,PLOT_SHOW_DATA,false) 进一步关掉主图数值面板,避免 ABCR 这类辅助指标污染报价窗。 短名用 "ABCR "+IntegerToString(magic_numb) 动态拼接,多实例加载时靠 magic_numb 区分;精度直接吃 _Digits,省去手动对齐小数位的麻烦。 真正容易踩坑的是 func_calc_date_start:它用 Bars() 反推实际可得 K 线数,若初始日期拉得太早、超出 Price[] 数组容量,就按 864000 秒(即 10 天)为步长往前挪 input_data_start,直到 Bars_Size 不大于 Array_Size 才停。外汇与贵金属杠杆高、跳空频繁,历史样本不足时这套收缩逻辑能避免数组越界崩指标,但也可能悄悄砍掉你预设的回测起点。 func_copy_price 的 price_type 用 0~3 映射 Close/Open/High/Low,内部靠静态数组 price_interim 暂存副本、bars_to_copy 记条数,调用前先确认 result_copy 返回非负再处理,否则复制失败会被静默吞掉。

MQL5 / C++
SetIndexBuffer(class="num">6,Date,INDICATOR_CALCULATIONS);      class=class="str">"cmt">// initialize data buffer
SetIndexBuffer(class="num">7,Price_high,INDICATOR_CALCULATIONS); class=class="str">"cmt">// initialize high price
SetIndexBuffer(class="num">8,Price_low,INDICATOR_CALCULATIONS);  class=class="str">"cmt">// initialize low price
class=class="str">"cmt">//--- set data which will not be drawn
PlotIndexSetDouble(class="num">0,PLOT_EMPTY_VALUE,class="num">0);
class=class="str">"cmt">//--- set the indicator appearance
IndicatorSetString(INDICATOR_SHORTNAME,"ABCR "+IntegerToString(magic_numb)); class=class="str">"cmt">// indicator name
class=class="str">"cmt">//--- display accuracy
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
class=class="str">"cmt">//--- prohibit display of the results of the indicator current values
PlotIndexSetInteger(class="num">0,PLOT_SHOW_DATA,class="kw">false);
class=class="str">"cmt">//--- assign start date variable value
date_start=first_date_start;
class=class="str">"cmt">//---
class="kw">return(INIT_SUCCEEDED);
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Func Calculate Date Start                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">datetime func_calc_date_start(class="type">class="kw">datetime input_data_start,class=class="str">"cmt">// initially start date set
                              class="type">class="kw">datetime data_stop)      class=class="str">"cmt">// calculation end date(current date)
class=class="str">"cmt">//---
  {
   class="type">int Array_Size=ArraySize(Price);
   class="type">int Bars_Size=Bars(_Symbol,time_frame,input_data_start,data_stop);
   for(;Bars_Size>Array_Size;input_data_start+=class="num">864000) class=class="str">"cmt">// class="num">864000 = class="num">10 days
     {
      Bars_Size=Bars(_Symbol,time_frame,input_data_start,data_stop);
     }
   class="kw">return(input_data_start);
class=class="str">"cmt">//---
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Func Copy Price                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool func_copy_price(class="type">class="kw">double &result_array[],
                     ENUM_TIMEFRAMES period,class=class="str">"cmt">// Timeframe
                     class="type">class="kw">datetime data_start,
                     class="type">class="kw">datetime data_stop,
                     class="type">char price_type) class=class="str">"cmt">// class="num">0-Close, class="num">1-Open, class="num">2-High, class="num">3-Low
  {
class=class="str">"cmt">//---
   class="type">int x=class="kw">false;       class=class="str">"cmt">// Variable for answering
   class="type">int result_copy=-class="num">1; class=class="str">"cmt">// copied data number
class=class="str">"cmt">//---
   class="kw">static class="type">class="kw">double price_interim[]; class=class="str">"cmt">// Temporal dynamic array for storing copied data
   class="kw">static class="type">int bars_to_copy;       class=class="str">"cmt">// number of bars to copy

「增量拷贝时四种价格的计数分轨」

在 MT5 自定义指标里做历史数据增量加载,最容易被忽略的是 Close / Open / High / Low 四条价格序列的已拷贝根数必须分开记账。上面用 static int 声明了 bars_copied_0 到 bars_copied_3 外加一个通用 bars_copied,分别对应四种价格类型的起始日以来已复制柱数,避免互相串扰。 一旦检测到起始日期变更(date_change==true),代码通过 ZeroMemory 把 price_interim、bars_to_copy 以及全部 bars_copied_* 清零。这一步很关键:若不清零,旧计数会叠加到新时间窗口,导致 CopyClose 等函数少拉或多拉数据,回测时可能悄无声息地错位。 实际拷贝前先用 Bars(_Symbol,period,data_start,data_stop) 取当前时间范围内总柱数,再减去对应 price_type 下已拷贝的柱数得到本次需补的 bars_to_copy。注意当 bars_copied 非零(非首次)时,代码令 bars_copied-- 且 bars_to_copy++,相当于把上一根重叠柱让出来重拷,保证序列连续不丢边界。 最后按 price_type 走 switch 调 CopyClose / CopyOpen / CopyHigh / CopyLow,目标数组用 ArrayResize 按 bars_to_copy 动态扩容。外汇与贵金属行情跳空频繁,这种分轨计数逻辑能降低重连后数据断裂的概率,但这类品种杠杆高、滑点风险大,任何数据层优化都不构成方向判断依据。

MQL5 / C++
  class="kw">static class="type">int bars_copied_0;          class=class="str">"cmt">// number of copied bars from Close start date
  class="kw">static class="type">int bars_copied_1;          class=class="str">"cmt">// number of copied bars from Open start date
  class="kw">static class="type">int bars_copied_2;          class=class="str">"cmt">// number of copied bars from High start date
  class="kw">static class="type">int bars_copied_3;          class=class="str">"cmt">// number of copied bars from Low start date
  class="kw">static class="type">int bars_copied;            class=class="str">"cmt">// number of copied bars from the common variable start date
class=class="str">"cmt">//--- variables reset due to changes in a start date
  if(date_change==true)
    {
      ZeroMemory(price_interim);
      ZeroMemory(bars_to_copy);
      ZeroMemory(bars_copied_0);
      ZeroMemory(bars_copied_1);
      ZeroMemory(bars_copied_2);
      ZeroMemory(bars_copied_3);
      ZeroMemory(bars_copied);
    }
class=class="str">"cmt">//--- get an information about the current bars number on the timeframe
  bars_to_copy=Bars(_Symbol,period,data_start,data_stop);
class=class="str">"cmt">//--- assign a copied function value to a common variable
  class="kw">switch(price_type)
    {
      case class="num">0:
        class=class="str">"cmt">//--- Close
        bars_copied=bars_copied_0;
        class="kw">break;
      case class="num">1:
        class=class="str">"cmt">//--- Open
        bars_copied=bars_copied_1;
        class="kw">break;
      case class="num">2:
        class=class="str">"cmt">//--- High
        bars_copied=bars_copied_2;
        class="kw">break;
      case class="num">3:
        class=class="str">"cmt">//--- Low
        bars_copied=bars_copied_3;
        class="kw">break;
    }
class=class="str">"cmt">//--- calculate number of bars required to be copied
  bars_to_copy-=bars_copied;
class=class="str">"cmt">//--- if it is not the first time the data has been copied
  if(bars_copied!=class="num">0)
    {
      bars_copied--;
      bars_to_copy++;
    }
class=class="str">"cmt">//--- change the size of the recieving array
  ArrayResize(price_interim,bars_to_copy);
class=class="str">"cmt">//--- copy data to the recieving array
  class="kw">switch(price_type)
    {
      case class="num">0:
        class=class="str">"cmt">//--- Close
        {
         result_copy=CopyClose(_Symbol,period,class="num">0,bars_to_copy,price_interim);
        }
      class="kw">break;
      case class="num">1:
        class=class="str">"cmt">//--- Open
        {
         result_copy=CopyOpen(_Symbol,period,class="num">0,bars_to_copy,price_interim);
        }
      class="kw">break;
      case class="num">2:
        class=class="str">"cmt">//--- High
        {

◍ 用中间数组接管多类型报价拷贝

这段逻辑把 High、Low 等不同价格类型的批量拷贝收口到同一个流程里:先按 price_type 分支调用 CopyHigh / CopyLow 等,把数据塞进临时数组 price_interim,返回实际拷贝根数 result_copy。 若 result_copy 不等于 -1,说明本次拷贝成功,立刻用 ArrayCopy 把临时数组搬进主结果数组 result_array,偏移量由已处理根数 bars_copied 决定,再把 x 置为 true、累加 bars_copied。外汇与贵金属行情跳空频繁,拷贝失败返回 -1 的概率不低,必须靠这个判断拦掉脏数据。 随后又用一次 switch 把最终的 bars_copied 按类型写回 bars_copied_0~3,方便上层知道 Close/Open/High/Low 各自落了多少根。下面附的 func_copy_date 则换成按 datetime 区间抽时间轴,静态变量 time_interim、bars_to_copy、bars_copied 在起始时间变动时才重置,避免重复分配。 开 MT5 把这段直接塞进 EA 的 OnTick 前跑一遍,改 period 为 PERIOD_M15 并观察 bars_copied_2 的累加值,能验证 High 序列是否连续无断点。

MQL5 / C++
result_copy=CopyHigh(_Symbol,period,class="num">0,bars_to_copy,price_interim);
class="kw">break;
case class="num">3:
 class=class="str">"cmt">//--- Low
 {
 result_copy=CopyLow(_Symbol,period,class="num">0,bars_to_copy,price_interim);
 }
 class="kw">break;
 }
class=class="str">"cmt">//--- check the result of data copying
 if(result_copy!=-class="num">1) class=class="str">"cmt">// if copying to the intermediate array is successful
  {
  ArrayCopy(result_array,price_interim,bars_copied,class="num">0,WHOLE_ARRAY); class=class="str">"cmt">// copy the data from the temporary array to the main one
  x=true; class=class="str">"cmt">// assign the positive answer to the function
  bars_copied+=result_copy; class=class="str">"cmt">// increase the value of the processed data
  }
class=class="str">"cmt">//--- class="kw">return the information about the processed data with one of the copied variables
 class="kw">switch(price_type)
  {
   case class="num">0:
    class=class="str">"cmt">//--- Close
    bars_copied_0=bars_copied;
    class="kw">break;
   case class="num">1:
    class=class="str">"cmt">//--- Open
    bars_copied_1=bars_copied;
    class="kw">break;
   case class="num">2:
    class=class="str">"cmt">//--- High
    bars_copied_2=bars_copied;
    class="kw">break;
   case class="num">3:
    class=class="str">"cmt">//--- Low
    bars_copied_3=bars_copied;
    class="kw">break;
  }
class=class="str">"cmt">//---
 class="kw">return(x);
 }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Func Copy Date                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool func_copy_date(class="type">class="kw">double &result_array[],
                   ENUM_TIMEFRAMES period,class=class="str">"cmt">// timeframe
                   class="type">class="kw">datetime data_start,
                   class="type">class="kw">datetime data_stop)
  {
class=class="str">"cmt">//---
  class="type">int x=class="kw">false; class=class="str">"cmt">// variable for answer
  class="type">int result_copy=-class="num">1; class=class="str">"cmt">// number of copied data
  class="kw">static class="type">class="kw">datetime time_interim[]; class=class="str">"cmt">// temporaty dynamic array for storing the copied data
  class="kw">static class="type">int bars_to_copy; class=class="str">"cmt">// bars number required to be copied
  class="kw">static class="type">int bars_copied; class=class="str">"cmt">// copied bars with start date
class=class="str">"cmt">//--- variables reset due to the start date change

增量拷贝与时间砖绘制的收尾实现

在日期切换标记置真时,先把三个缓冲数组清零,避免上一交易周期残留的时间戳污染新周期的分段统计。这一步在外汇与贵金属这类跳空频繁的品种上尤其关键,MT5 默认不会替你清空跨日残留,手动 ZeroMemory 能降低后续 Bars() 计数偏差的概率。 增量拷贝的核心是先算尚需复制的 bar 数:用 Bars() 取当前区间总 bar 数,再减去已拷贝数。若非首次拷贝,则已拷贝数减一、待拷贝数加一,用来补回上一轮末尾可能重复的那一根,保证 Renko 砖时间序列连续不断层。 func_calc_dorstep 给出两种砖高算法:type_doorstep 为 0 时直接取点数;为 1 时按百分比换算成点数,公式是 price/_Point*doorstep/100。黄金若设 0.1% 砖高、现价 2300,算出来约 230 点,回测时可直接改这个参数看噪讯比变化。 func_draw_renko 接收价格与日期引用数组、反转过滤砖数、阴影开关与砖高类型,把前面的缓冲结果落成图形。外汇与贵金属杠杆高、滑点风险大,任何砖型参数都先在策略测试器用历史数据验证,再上实盘。

MQL5 / C++
  if(date_change==true)
    {
      ZeroMemory(time_interim);
      ZeroMemory(bars_to_copy);
      ZeroMemory(bars_copied);
    }
class=class="str">"cmt">//---
  bars_to_copy=Bars(_Symbol,period,data_start,data_stop); class=class="str">"cmt">// Find out the current number of bars on the time interval
  bars_to_copy-=bars_copied; class=class="str">"cmt">// Calculate the number of bars to be copied
class=class="str">"cmt">//---
  if(bars_copied!=class="num">0) class=class="str">"cmt">// If it is not the first time the data has been copied
    {
      bars_copied--;
      bars_to_copy++;
    }
class=class="str">"cmt">//---
  ArrayResize(time_interim,bars_to_copy); class=class="str">"cmt">// Change the size of the receiving array
  result_copy=CopyTime(_Symbol,period,class="num">0,bars_to_copy,time_interim);
class=class="str">"cmt">//---
  if(result_copy!=-class="num">1) class=class="str">"cmt">// If copying to the intermediate array is successful
    {
      ArrayCopy(result_array,time_interim,bars_copied,class="num">0,WHOLE_ARRAY); class=class="str">"cmt">// Copy the data from the temporary array to the main one
      x=true; class=class="str">"cmt">// assign the positive answer to the function
      bars_copied+=result_copy; class=class="str">"cmt">// Increase the value of the processed data
    }
class=class="str">"cmt">//---
  class="kw">return(x);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Func Calculate Doorstep                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int func_calc_dorstep(class="type">class="kw">double price,    class=class="str">"cmt">// price
                      class="type">char type_doorstep,class=class="str">"cmt">// step type
                      class="type">class="kw">double doorstep)  class=class="str">"cmt">// step
  {
  class="type">class="kw">double x=class="num">0;          class=class="str">"cmt">// variable for answer
  if(type_doorstep==class="num">0) class=class="str">"cmt">// If the calculation is to be performed in points
    {
      x=doorstep;
    }
  if(type_doorstep==class="num">1) class=class="str">"cmt">// If the calculation is to be performed in percentage
    {
      x=price/_Point*doorstep/class="num">100;
    }
  class="kw">return((class="type">int)x);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Func Draw Renko                                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void func_draw_renko(class="type">class="kw">double &price[],   class=class="str">"cmt">// prices array
                     class="type">class="kw">double &date[],    class=class="str">"cmt">// date array
                     class="type">int number_filter, class=class="str">"cmt">// bricks number for reversal
                     class="type">bool draw_shadow,  class=class="str">"cmt">// draw shadow
                     class="type">char type_doorstep,class=class="str">"cmt">// step type
把砖块重绘交给小布盯盘
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到 Renko 砖块生成是否偏离你的箱体设定,你只管调参数和看形态。

常见问题

首块砖依据价格行为绘制,其柱线开盘价取自前一块砖的最大最小值,之后按收盘价与前砖极值比较决定白黑砖。
指标可随新 tick 动态重绘砖块并挂载窗口,脚本多为一次性输出,难以持续跟踪价格走势生成新砖。
可以,把编译好的自定义指标放进对应品种页,小布盯盘的 AIGC 层会读取砖块序列辅助你识别趋势延续或反转概率。
外汇和贵金属杠杆高、波动随机,30 点箱体在消息面行情可能连续出砖,请先用模拟盘验证再上实盘。
Renko 每突破箱体就新竖排一块砖且颜色看收闭价方向,Kagi 则按反向阈值反转主线粗细,二者忽略时间的方式类似但结构不同。