RSI深三步交易技巧
1. 概述
本文基于一系列新的研究,这些研究展示了一些基于RSI的交易技术。交易技巧是使用指标的一种方式。本研究基于mql5编码语言。
2. RSI简介
RSI代表相对强度指数,这是一种技术分析指标,用于衡量股票、货币或商品等证券的强度和动量。RSI是使用数学公式计算的,并绘制在图表上,以直观地表示给定时期内证券的强弱程度。
RSI基于这样一个原则,即随着价格上涨,证券变得超买,而随着价格下跌,证券变得超卖。RSI帮助交易者识别潜在的趋势反转或价格修正。
RSI计算包括将证券在给定时期的平均收益与证券在同一时期的平均损失进行比较。RSI的默认版本绘制在0到100的范围内,读数高于70被视为超买,读数低于30被视为超卖。RSI在交易员中是一个受欢迎的指标,因为它可以提供潜在市场趋势的早期预警信号。例如,如果一种证券的RSI持续上升并达到70以上的水平,这可能表明该证券超买,应进行调整。另一方面,如果RSI持续下跌并达到30以下的水平,这可能表明该证券超卖,并将出现反弹。
值得注意的是,RSI不应单独用作做出交易决策的唯一依据。交易员通常将RSI与其他技术分析工具和市场指标结合使用,以更全面地了解市场状况,并做出明智的交易决策。一般来说,RSI是以周期数14来计算的。
3. 什么是RSI(更深入的描述)。
3.1概述相对强弱指数(RSI)是一种用于金融市场分析的技术指标。它旨在根据最近交易期的收盘价绘制股票或市场的当前和历史强弱。指标不应与相对强度混淆。
RSI被归类为动量振荡器,用于测量价格波动的速度和幅度。动量是指价格上涨或下跌的速度。相对强度RS以较高收盘价与较低收盘价的比率给出。具体地说,计算收盘价变化绝对值的两个平均值,即蜡烛图中蜡烛大小的两个总和。RSI将动量计算为较高收盘价与总收盘价的比率:具有更多或更强正变化的股票比具有更多或更强烈负变化的股票具有更高的RSI。
RSI最常用于14天的时间段,尺度范围是从0到100,高水平和低水平分别标记为70和30。更短或更长的时间框架对应用于更短或更长的展望。高和低水平——80和20,或90和10——出现的频率较低,但表明动量更强。
相对强度指数由J. Welles Wilder 开发,并发表在1978年出版的《技术交易系统中的新概念》一书和1978年6月出版的《商品》杂志(现为《现代交易员》杂志)上。它已成为最受欢迎的振荡指数之一。
RSI提供信号,告诉投资者在证券或货币超卖时买入,在超买时卖出。
Marek和Šedivá(2017)对具有推荐参数的RSI及其日常优化进行了测试,并与其他策略进行了比较。该测试在时间和公司(例如,苹果、埃克森美孚、IBM、微软)中是随机的,表明RSI仍然可以产生良好的结果;然而,在较长的时间范围内,它通常被简单的买入和持有策略击败。
3.2计算对于每个交易周期,计算向上变化U或向下变化D。上涨期的特点是收盘价高于前一收盘价:
反之下跌时段的特征在于收盘低于前一时段的收盘,
如果最后一次收盘价与前一次收盘价相同,则U和D都为零。请注意,U和D都是正数。
现在,使用n周期平滑或修改的移动平均值(SMMA或MMA),即α=1/n的指数平滑移动平均值,从U和D的序列计算平均值。这些是这些正项的正加权平均值,并且相对于分区表现为加法。
Wilder 最初将移动平均值的计算公式化为:newval=(preval*(n-1)+newdata)/n,这相当于前面提到的指数平滑。因此,将新数据简单地除以n,或乘以α,并将以前的平均值修改为(n-1)/n,即1-α。一些商业软件包,如AIQ,使用标准指数移动平均值(EMA)作为平均值,而不是Wilder的SMMA。应该使用价格序列中的前n个值,使用简单的移动平均值来适当地初始化平滑移动平均值。
这些平均值的比率是相对强度或相对强度因子:
然后将相对强度因子转换为0和100之间的相对强度指数:
如果U值的平均值为零,则RS和RSI也为零。如果U值的平均值等于D值的平均数,则RS为1,RSI为50。如果U值的平均值是最大的,使得D值的平均为零,则RS值发散到无穷大,而RSI为100。
3.3解释
3.3.1基本配置RSI显示在价格图上方或下方的图表上。该指标具有通常在70处的上线、在30处的下线和在50处的虚线中线。Wilder建议平滑周期为14(参见指数平滑,即α=1/14或N=14)。
3.3.2. 原则
Wilder 认为,当价格迅速上涨时,在某种程度上会被视为超买。同样,当价格迅速下跌时,在某些时候会被视为超卖。无论哪种情况,Wilder 都认为反应或逆转迫在眉睫。
RSI的水平是衡量股票最近交易实力的指标。RSI的斜率与趋势变化的速度成正比。RSI行进的距离与移动的幅度成比例。
Wilder 认为,当RSI高于70或降至30以下时,顶部和底部都会显示出来。传统上,RSI读数大于70水平被认为处于超买区域,而RSI读数低于30水平被认为位于超卖区域。介于30和70之间的水平被认为是中性的,而50水平则是没有趋势的迹象。
3.3.3. 背离
Wilder 进一步认为,RSI和价格走势之间的差异是一个非常强烈的迹象,表明市场转折点即将到来。当价格创下新高,但RSI创下较低高点,从而无法确认时,就会出现空头背离。当价格创下新低,但RSI创下更高的低点时,就会出现牛市背离。
3.3.4. 超买和超卖情况Wilder认为,RSI在50以上和50以下的“失败波动”是市场逆转的有力迹象。例如,假设RSI达到76,回落到72,然后上升到77。如果它低于72,Wilder会认为这是高于70的“失败摆动”。
最后,Wilder写道,与价格图相比,RSI图上有时更容易看到图表形成以及支撑和阻力区域。相对强度指数的中心线是50,这通常被视为指标的支撑线和阻力线。
如果相对强弱指数低于50,通常意味着股票的损失大于收益。当相对强度指数高于50时,通常意味着收益大于损失。
3.3.5. 上升趋势和下降趋势除了 Wilder 关于RSI解释的原始理论外,Andrew Cardwell还对RSI进行了一些新的解释,以帮助确定和确认趋势。首先,Cardwell注意到,上升趋势通常在RSI 40和80之间交易,而下降趋势通常在60和20之间交易。Cardwell观察到,当证券从上升趋势变为下降趋势,反之亦然时,RSI将经历“区间转换”
接下来,Cardwell指出,看跌背离:1)只发生在上升趋势,2)大多只会导致短暂的修正,而不是趋势的逆转。因此,看跌背离是确认上升趋势的信号。同样,看涨背离是确认下跌趋势的信号。
3.3.6. 反转最后,Cardwell发现RSI中存在正反转和负反转。反转与背离相反。例如,当上升趋势价格修正导致与上次价格修正相比更低的低点时,就会发生正反转,而RSI导致与上次修正相比更低的低点。当下跌趋势反弹导致与上一次下跌趋势反弹相比的较低高点时,就会发生负反转,但RSI使与前一次反弹相比的高点更高。
换言之,尽管RSI的高点或低点表现出更强的势头,但价格无法创造更高的高点或更低的低点。这是主要趋势即将恢复的证据。Cardwell指出,正反转只发生在上升趋势中,而负反转只出现在下降趋势中,因此它们的存在证实了这一趋势。4. RSI深三步
深三步技术有一个有趣的假设,该假设指出,通常每当RSI进入超卖或超买水平,并形成连续三次更深的移动,而第四次移动是确认(也必须更深),那么就可以给出信号。交易条件如下:
- 每当RSI低于前一个RSI时,就会检测到看涨信号,而前一个也低于其前一个,而后者也低于其先前的RSI。由于它通常与8周期RSI一起使用,三个周期前的RSI必须低于20,第四个周期前必须高于20(以避免重复信号)。
-
每当RSI高于先前RSI时,就会检测到看跌信号,而先前RSI又高于其先前RSI,而后者也高于其先前的RSI。由于它通常与8周期RSI一起使用,三个周期前的RSI必须高于80,第四个周期前必须低于80(以避免重复信号)。
一幅画胜过千言万语,下图显示了基于该技术的看涨信号:
5. 代码
//+------------------------------------------------------------------+ //| RSI Deep Three Move.mq5 | //| Javier S. Gastón de Iriarte Cabrera | //| https://https://www.mql5.com/en/users/jsgaston/news | //+------------------------------------------------------------------+ #property copyright "Javier S. Gastón de Iriarte Cabrera" #property link "https:/https://www.mql5.com/en/users/jsgaston/news" #property version "1.01" #property script_show_inputs #include <GetIndicatorBuffers.mqh> #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\PositionInfo.mqh> #include <Trade\AccountInfo.mqh> //--- CPositionInfo m_position; // object of CPositionInfo class CTrade m_trade; // object of CTrade class CSymbolInfo m_symbol; // object of CSymbolInfo class CAccountInfo m_account; // object of CAccountInfo class CTrade trade; CTrade Ctrade; input string Expert_Title ="RSI Deep Three Move Strategy"; // Document name enum ENUM_LOT_TYPE { LOT_TYPE_FIX = 0, // fix lot LOT_TYPE_RISK = 1, // risk % }; //--- input parameters input ENUM_LOT_TYPE inp_lot_type = LOT_TYPE_FIX; // type of lot input double inp_lot_fix = 0.01; // fix lot input double inp_lot_risk = 0.01; input bool InpPrintLog = false; // Print log ulong Expert_MagicNumber =11777; bool Expert_EveryTick =false; input ENUM_TIMEFRAMES my_timeframe=PERIOD_CURRENT; // Timeframe input ENUM_APPLIED_PRICE Inp_RSI_applied_price = PRICE_CLOSE; // RSI: type of price input int InpPeriodRSI=8; // Period of the signal for the RSI inside custom int handle_iCustom; input int ptsl = 5000; // points for stoploss input int pttp = 5000; // points for takeprofit string Orden; double sl2; double tp2;
这是一段用MQL5语言编写的复杂代码。这是一种使用相对强弱指数(RSI)来识别潜在交易机会的交易策略。该代码包括各种类的使用,如CPositionInfo、CTrade、CSymbolInfo和CAccountInfo。它还包括各种输入参数的使用,如手数类型、固定手数、风险百分比、EA交易标题、幻数、时间框架、RSI平均期、价格类型以及止损和获利点。该代码还包括对handle_iRSI2、handle_iCustom、Orden、sl和tp等变量的使用。此代码的目的是根据RSI指标识别潜在的交易机会。
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- handle_iCustom=iCustom(_Symbol,my_timeframe,"\\Indicators\\Examples\\RSI",InpPeriodRSI); if(handle_iCustom==INVALID_HANDLE) { //--- tell about the failure and output the error code PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d", _Symbol, EnumToString(my_timeframe), GetLastError()); //--- the indicator is stopped early return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); }
此代码是MQL5语言中EA交易初始化函数的一部分。它用于为给定交易品种和时间框架的iCustom指标创建句柄。它还为具有给定参数的iRSI指标创建句柄。如果无法创建iCustom指标的句柄,则会打印一条错误消息并停止指标。如果成功创建句柄,则初始化成功。
void OnTick() { MqlTick tick; double last_price = tick.ask; SymbolInfoTick(_Symbol,tick); int total = PositionsTotal(); //--- // Retrieve the current value MqlTradeResult result; MqlRates rates[]; //--- double array_rsi[]; ArraySetAsSeries(array_rsi,true); int start_pos=0,count=5; if(!iGetArray(handle_iCustom,0,start_pos,count,array_rsi)) return; string text=""; for(int i=0; i<count; i++) text=text+IntegerToString(i)+": "+DoubleToString(array_rsi[i],Digits()+1)+"\n"; //--- Comment(text); { if(array_rsi[0] < array_rsi[1] && array_rsi[1] < array_rsi[2] && array_rsi[2] < array_rsi[3] && array_rsi[3] < 20.0 && array_rsi[4] > 20.0) { Print("Open Order Buy"); Alert(" Buying"); Orden="Buy"; sl=NormalizeDouble(tick.ask - ptsl*_Point,_Digits); tp=NormalizeDouble(tick.bid + pttp*_Point,_Digits); trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,get_lot(tick.bid),tick.bid,sl,tp,"Buy"); return; } } { if(array_rsi[0] > array_rsi[1] && array_rsi[1] > array_rsi[2] && array_rsi[2] > array_rsi[3] && array_rsi[3] > 80.0 && array_rsi[4] < 80.0) { Print("Open Order Sell"); Alert(" Selling"); Orden="Sell"; sl=NormalizeDouble(tick.bid + ptsl*_Point,_Digits); tp=NormalizeDouble(tick.ask - pttp*_Point,_Digits); trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,get_lot(tick.ask),tick.ask,sl,tp,"Sell"); return; } } if(total>0) { if(Orden=="Sell" && array_rsi2[0]<20.0) { trade.PositionClose(_Symbol,5); Print("cerró sell"); return; } if(Orden=="Buy" && array_rsi2[0]>80.0) { trade.PositionClose(_Symbol,5); Print("cerró buy"); return; } } }这段代码是MQL5语言中的分时处理函数。它用于在市场上开仓和平仓。它首先检索交易品种的当前值,并将其存储在MqlTick tick变量中。然后,它检索仓位的总数,并将其存储在total变量中。然后,它从iCustom函数中检索RSI值,并将其存储在array_rsi和变量中。然后,它检查卖出订单的RSI值是否低于20,买入订单的RSI值是否高于80,如果是,它用相应的参数打开头寸。最后,它检查RSI值是否已经超过20或80的阈值,如果是,它关闭该仓位。
bool iGetArray(const int handle,const int buffer,const int start_pos, const int count,double &arr_buffer[]) { bool result=true; if(!ArrayIsDynamic(arr_buffer)) { //if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, this a no dynamic array!",__FILE__,__FUNCTION__); return(false); } ArrayFree(arr_buffer); //--- reset error code ResetLastError(); //--- fill a part of the iBands array with values from the indicator buffer int copied=CopyBuffer(handle,buffer,start_pos,count,arr_buffer); if(copied!=count) { //--- if the copying fails, tell the error code //if(InpPrintLog) PrintFormat("ERROR! EA: %s, FUNCTION: %s, amount to copy: %d, copied: %d, error code %d", __FILE__,__FUNCTION__,count,copied,GetLastError()); //--- quit with zero result - it means that the indicator is considered as not calculated return(false); } return(result); }
此代码用于将数值从指标缓冲区复制到数组中。该函数采用五个参数:指标的句柄、指标缓冲区、缓冲区中的起始位置、要复制的值的数量以及存储值的数组。然后,它检查数组是否是动态的,如果是,它会重置错误代码,并将值从缓冲区复制到数组中。如果复制失败,它将打印一条错误消息并返回false。否则,就返回true。
double get_lot(double price) { if(inp_lot_type==LOT_TYPE_FIX) return(normalize_lot(inp_lot_fix)); double one_lot_margin; if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,one_lot_margin)) return(inp_lot_fix); return(normalize_lot((AccountInfoDouble(ACCOUNT_BALANCE)*(inp_lot_risk/100))/ one_lot_margin)); } double normalize_lot(double lt) { double lot_step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); lt = MathFloor(lt / lot_step) * lot_step; double lot_minimum = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); lt = MathMax(lt, lot_minimum); return(lt); }
此代码用于计算交易的手数大小。第一个函数get_lot()将交易价格作为参数,并检查手数计算类型(固定或基于风险的)。如果手数类型是固定的,则调用normalize_lot()函数来规范化手数大小。如果手数类型是基于风险的,则OrderCalcMargin()函数用于计算交易所需的保证金,而AccountInfoDouble()函数则用于获取账户余额。然后通过将账户余额除以保证金并乘以风险百分比来计算手数大小。然后调用normalize_lot()函数来规范化手数大小。normalize_lot()函数以手数大小为参数,计算交易品种的步长和最小手数大小,然后将手数大小四舍五入到最接近的步长,并在必要时应用最小手数大小。
6. 结果
从2023年1月1日到6月底,EURUSD 30分钟周期,sl为900点(记住RSI使用8个周期)。
7. 结论
当然,并不是所有的技术都是完美的。你一定会遇到一些错误信号,特别是在有趋势期间。正如你可能也注意到的,在强劲的趋势中,这项技术并没有如预期的那样发挥作用。
该策略必须进行优化才能应用于市场,但其思想是提出一种关于市场分析的均值回归思维方式。
这些是我的经纪商在一个美分账户中的所有交易品种的盈利结果,从2023年到6月底,时段为30分钟。
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/12846