Files

458 lines
39 KiB
Markdown
Raw Permalink Normal View History

2023-12-11 09:35:59 +08:00
> Name
EMA-ADX-VOL-加密货币杀手EMA-ADX-VOL-CRYPTO-KILLER
> Author
ChaoZhang
> Strategy Description
![IMG](https://www.fmz.com/upload/asset/1c9e738520dfa402fba.png)
[trans]
利用EMA均线系统判断趋势方向,ADX指标判断趋势强弱,并结合交易量过滤进行入场的量化交易策略
## 原理
该策略首先利用5条不同周期的EMA均线判断价格趋势方向,当5条EMA均线全部上涨时判断为多头趋势形成,当5条EMA均线全部下跌时判断为空头趋势形成。
然后利用ADX指标判断趋势的强弱,当DI+线高于DI-线且ADX值超过设定阈值时判断为强势多头行情,当DI-线高于DI+线且ADX值超过设定阈值时判断为空头行情。
同时,利用交易量的突破进行额外确认,要求当前K线交易量要大于一定周期均量的倍数,从而避免在低量位置错误入场。
结合趋势方向、趋势强度和交易量的综合判断,形成该策略的多头和空头开仓逻辑。
## 优势
1. 使用EMA均线系统判断趋势方向,比单一EMA均线判断更加可靠。
2. 借助ADX指标判断趋势强弱,避免在无明确趋势时错误入场。
3. 交易量过滤机制,确保有充足的交易量支持,增强策略可靠性。
4. 多重条件综合判断,开仓信号更加精确可靠。
5. 策略参数较多,可以通过参数优化不断提升策略效果。
## 风险及解决
1. 在震荡行情中,EMA均线、ADX等判断可能发出错误信号,从而产生不必要的亏损,可以适当调整参数,或增加其他指标进行辅助判断。
2. 交易量过滤条件过于严格,可能错过行情机会,可以适当降低交易量过滤的参数。
3. 策略产生的交易频率可能较高,需要注意资金管理,适当控制单笔仓位规模。
## 优化方向
1. 测试不同参数组合,寻找最佳参数,提升策略效果。
2. 增加其他指标,如MACD、KDJ等与EMA和ADX进行组合,形成更强大的综合开仓判断。
3. 添加止损策略,进一步控制风险。
4. 优化仓位管理策略,实现更科学的资金管理。
## 总结
该策略综合考虑价格趋势方向、趋势强度和交易量信息,形成开仓规则,在一定程度上避免了误入常见陷阱,具有较强的可靠性。但仍需要进一步通过参数优化、指标优选以及风险控制来完善策略系统,将效果进一步提升。总的来说,该策略框架具有很大的拓展潜力和优化空间。
||
A quantitative trading strategy that uses an EMA system to determine trend direction, ADX indicator to determine trend strength, and incorporates trading volume filtering for entry
## Principle
The strategy first uses 5 EMAs of different periods to judge the price trend direction. When all 5 EMAs rise, it is judged as a bullish trend formation. When all 5 EMAs fall, it is judged as a bearish trend formation.
It then uses the ADX indicator to judge the strength of the trend. When the DI+ line is higher than the DI- line and the ADX value exceeds the set threshold, it is judged as a strong bullish trend. When the DI- line is higher than the DI+ line and the ADX value exceeds the set threshold, it is judged as a bearish trend.
At the same time, breakthroughs in trading volume are used for additional confirmation, requiring the trading volume of the current K-line to be greater than a certain multiple of the mean volume over a period, thereby avoiding wrong entries in low volume positions.
Combined with the comprehensive judgment of trend direction, trend strength and trading volume, the long and short opening logic of this strategy is formed.
## Advantages
1. Using an EMA system to judge trend direction is more reliable than a single EMA.
2. Using the ADX indicator to judge the strength of the trend avoids wrong entries when there is no clear trend.
3. The trading volume filter mechanism ensures sufficient trading volume support and enhances the reliability of the strategy.
4. Multiple condition comprehensive judgment makes opening signals more precise and reliable.
5. The relatively large number of strategy parameters allows performance improvements through ongoing parameter optimization.
## Risks and Solutions
1. In range-bound markets, EMA, ADX and other judgments may give wrong signals, resulting in unnecessary losses. Parameters can be adjusted appropriately or other indicators can be added for auxiliary judgment.
2. The trading volume filter conditions may be too strict, missing market opportunities. The parameters can be appropriately reduced.
3. The trading frequency generated by the strategy may be relatively high. Attention should be paid to money management and the size of single positions should be appropriately controlled.
## Optimization Directions
1. Test different parameter combinations to find optimal parameters to improve strategy performance.
2. Add other indicators such as MACD, KDJ to combine with EMA and ADX to form a more powerful comprehensive open position judgment.
3. Add stop loss strategies to further control risks.
4. Optimize position management strategies to achieve more scientific capital management.
## Summary
By comprehensively considering price trend direction, trend strength and trading volume information, this strategy forms opening rules to avoid some common traps to some extent and has relatively strong reliability. But it still needs further improvement of the strategy system through parameter optimization, indicator selection and risk control to further improve performance. In general, this strategy framework has great potential for expansion and optimization space.
[/trans]
> Strategy Arguments
|Argument|Default|Description|
|----|----|----|
|v_input_1_open|0|  Source: open|high|low|close|hl2|hlc3|hlcc4|ohlc4|
|v_input_5|8|  1-EMA Length|
|v_input_6|13|  2-EMA Length|
|v_input_7|21|  3-EMA Length|
|v_input_8|34|  4-EMA Length|
|v_input_9|55|  5-EMA Length|
|v_input_2|0|(?ADX)  Adx Type: MASANAKAMURA|CLASSIC|
|v_input_3|21|  Adx Length|
|v_input_4|20|  Adx Treshold|
|v_input_10|15|(?Range Filter)  Period|
|v_input_11|2.6|  mult.|
|v_input_12|3.2|(?Volume)  Volume mult.|
|v_input_13|20|  Volume lenght|
|v_input_14|1.9|  Volume mult. 1|
|v_input_15|22|  Volume lenght 1|
|v_input_16|0.9|(?Target Point)  % TP Long|
|v_input_17|0.9|  % TP Short|
|v_input_18|4.2|(?Stop Loss)  % Stop loss|
> Source (PineScript)
2024-03-03 22:27:55 +08:00
``` pinescript
2023-12-11 09:35:59 +08:00
/*backtest
start: 2022-11-28 00:00:00
end: 2023-12-04 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © BabehDyo
//@version=4
strategy("EMA/ADX/VOL-CRYPTO KILLER [15M]", overlay = true, pyramiding=1,initial_capital = 10000, default_qty_type= strategy.percent_of_equity, default_qty_value = 100, calc_on_order_fills=false, slippage=0,commission_type=strategy.commission.percent,commission_value=0.03)
//SOURCE =============================================================================================================================================================================================================================================================================================================
src = input(open, title="  Source")
// Inputs ========================================================================================================================================================================================================================================================================================================
//ADX --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ADX_options = input("MASANAKAMURA", title="  Adx Type", options = ["CLASSIC", "MASANAKAMURA"], group="ADX")
ADX_len = input(21, title="  Adx Length", type=input.integer, minval = 1, group="ADX")
th = input(20, title="  Adx Treshold", type=input.float, minval = 0, step = 0.5, group="ADX")
//EMA--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Length_ema1 = input(8, title="  1-EMA Length", minval=1)
Length_ema2 = input(13, title="  2-EMA Length", minval=1)
Length_ema3 = input(21, title="  3-EMA Length", minval=1)
Length_ema4 = input(34, title="  4-EMA Length", minval=1)
Length_ema5 = input(55, title="  5-EMA Length", minval=1)
// Range Filter ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
per_ = input(15, title="  Period", minval=1, group = "Range Filter")
mult = input(2.6, title="  mult.", minval=0.1, step = 0.1, group = "Range Filter")
// Volume ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
volume_f = input(3.2, title="  Volume mult.", minval = 0, step = 0.1, group="Volume")
sma_length = input(20, title="  Volume lenght", minval = 1, group="Volume")
volume_f1 = input(1.9, title="  Volume mult. 1", minval = 0, step = 0.1, group="Volume")
sma_length1 = input(22, title="  Volume lenght 1", minval = 1, group="Volume")
//TP PLOTSHAPE -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tp_long0 = input(0.9, title="  % TP Long", type = input.float, minval = 0, step = 0.1, group="Target Point")
tp_short0 = input(0.9, title="  % TP Short", type = input.float, minval = 0, step = 0.1, group="Target Point")
// SL PLOTSHAPE ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
sl0 = input(4.2, title="  % Stop loss", type = input.float, minval = 0, step = 0.1, group="Stop Loss")
//INDICATORS =======================================================================================================================================================================================================================================================================================================
//ADX-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
calcADX(_len) =>
up = change(high)
down = -change(low)
plusDM = na(up) ? na : (up > down and up > 0 ? up : 0)
minusDM = na(down) ? na : (down > up and down > 0 ? down : 0)
truerange = rma(tr, _len)
_plus = fixnan(100 * rma(plusDM, _len) / truerange)
_minus = fixnan(100 * rma(minusDM, _len) / truerange)
sum = _plus + _minus
_adx = 100 * rma(abs(_plus - _minus) / (sum == 0 ? 1 : sum), _len)
[_plus,_minus,_adx]
calcADX_Masanakamura(_len) =>
SmoothedTrueRange = 0.0
SmoothedDirectionalMovementPlus = 0.0
SmoothedDirectionalMovementMinus = 0.0
TrueRange = max(max(high - low, abs(high - nz(close[1]))), abs(low - nz(close[1])))
DirectionalMovementPlus = high - nz(high[1]) > nz(low[1]) - low ? max(high - nz(high[1]), 0) : 0
DirectionalMovementMinus = nz(low[1]) - low > high - nz(high[1]) ? max(nz(low[1]) - low, 0) : 0
SmoothedTrueRange := nz(SmoothedTrueRange[1]) - (nz(SmoothedTrueRange[1]) /_len) + TrueRange
SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - (nz(SmoothedDirectionalMovementPlus[1]) / _len) + DirectionalMovementPlus
SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - (nz(SmoothedDirectionalMovementMinus[1]) / _len) + DirectionalMovementMinus
DIP = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100
DIM = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100
DX = abs(DIP-DIM) / (DIP+DIM)*100
adx = sma(DX, _len)
[DIP,DIM,adx]
[DIPlusC,DIMinusC,ADXC] = calcADX(ADX_len)
[DIPlusM,DIMinusM,ADXM] = calcADX_Masanakamura(ADX_len)
DIPlus = ADX_options == "CLASSIC" ? DIPlusC : DIPlusM
DIMinus = ADX_options == "CLASSIC" ? DIMinusC : DIMinusM
ADX = ADX_options == "CLASSIC" ? ADXC : ADXM
L_adx = DIPlus > DIMinus and ADX > th
S_adx = DIPlus < DIMinus and ADX > th
//EMA-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
xPrice = close
EMA1 = ema(xPrice, Length_ema1)
EMA2 = ema(xPrice, Length_ema2)
EMA3 = ema(xPrice, Length_ema3)
EMA4 = ema(xPrice, Length_ema4)
EMA5 = ema(xPrice, Length_ema5)
L_ema = EMA1 < close and EMA2 < close and EMA3 < close and EMA4 < close and EMA5 < close
S_ema = EMA1 > close and EMA2 > close and EMA3 > close and EMA4 > close and EMA5 > close
// Range Filter ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var bool L_RF = na, var bool S_RF = na
Range_filter(_src, _per_, _mult)=>
var float _upward = 0.0
var float _downward = 0.0
wper = (_per_*2) - 1
avrng = ema(abs(_src - _src[1]), _per_)
_smoothrng = ema(avrng, wper)*_mult
_filt = _src
_filt := _src > nz(_filt[1]) ? ((_src-_smoothrng) < nz(_filt[1]) ? nz(_filt[1]) : (_src-_smoothrng)) : ((_src+_smoothrng) > nz(_filt[1]) ? nz(_filt[1]) : (_src+_smoothrng))
_upward := _filt > _filt[1] ? nz(_upward[1]) + 1 : _filt < _filt[1] ? 0 : nz(_upward[1])
_downward := _filt < _filt[1] ? nz(_downward[1]) + 1 : _filt > _filt[1] ? 0 : nz(_downward[1])
[_smoothrng,_filt,_upward,_downward]
[smoothrng, filt, upward, downward] = Range_filter(src, per_, mult)
hband = filt + smoothrng
lband = filt - smoothrng
L_RF := high > hband and upward > 0
S_RF := low < lband and downward > 0
// Volume -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Volume_condt = volume > sma(volume,sma_length)*volume_f
Volume_condt1 = volume > sma(volume,sma_length1)*volume_f1
//STRATEGY ==========================================================================================================================================================================================================================================================================================================
var bool longCond = na, var bool shortCond = na
var int CondIni_long = 0, var int CondIni_short = 0
var bool _Final_longCondition = na, var bool _Final_shortCondition = na
var float last_open_longCondition = na, var float last_open_shortCondition = na
var int last_longCondition = na, var int last_shortCondition = na
var int last_Final_longCondition = na, var int last_Final_shortCondition = na
var int nLongs = na, var int nShorts = na
L_1 = L_adx and Volume_condt and L_RF and L_ema
S_1 = S_adx and Volume_condt and S_RF and S_ema
L_2 = L_adx and L_RF and L_ema and Volume_condt1
S_2 = S_adx and S_RF and S_ema and Volume_condt1
L_basic_condt = L_1 or L_2
S_basic_condt = S_1 or S_2
longCond := L_basic_condt
shortCond := S_basic_condt
CondIni_long := longCond[1] ? 1 : shortCond[1] ? -1 : nz(CondIni_long[1] )
CondIni_short := longCond[1] ? 1 : shortCond[1] ? -1 : nz(CondIni_short[1] )
longCondition = (longCond[1] and nz(CondIni_long[1]) == -1 )
shortCondition = (shortCond[1] and nz(CondIni_short[1]) == 1 )
//POSITION PRICE-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var float sum_long = 0.0, var float sum_short = 0.0
var float Position_Price = 0.0
last_open_longCondition := longCondition ? close[1] : nz(last_open_longCondition[1] )
last_open_shortCondition := shortCondition ? close[1] : nz(last_open_shortCondition[1] )
last_longCondition := longCondition ? time : nz(last_longCondition[1] )
last_shortCondition := shortCondition ? time : nz(last_shortCondition[1] )
in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition
last_Final_longCondition := longCondition ? time : nz(last_Final_longCondition[1] )
last_Final_shortCondition := shortCondition ? time : nz(last_Final_shortCondition[1] )
nLongs := nz(nLongs[1] )
nShorts := nz(nShorts[1] )
if longCondition
nLongs := nLongs + 1
nShorts := 0
sum_long := nz(last_open_longCondition) + nz(sum_long[1])
sum_short := 0.0
if shortCondition
nLongs := 0
nShorts := nShorts + 1
sum_short := nz(last_open_shortCondition)+ nz(sum_short[1])
sum_long := 0.0
Position_Price := nz(Position_Price[1])
Position_Price := longCondition ? sum_long/nLongs : shortCondition ? sum_short/nShorts : na
//TP---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var bool long_tp = na, var bool short_tp = na
var int last_long_tp = na, var int last_short_tp = na
var bool Final_Long_tp = na, var bool Final_Short_tp = na
var bool Final_Long_sl0 = na, var bool Final_Short_sl0 = na
var bool Final_Long_sl = na, var bool Final_Short_sl = na
var int last_long_sl = na, var int last_short_sl = na
tp_long = ((nLongs > 1) ? tp_long0 / nLongs : tp_long0) / 100
tp_short = ((nShorts > 1) ? tp_short0 / nShorts : tp_short0) / 100
long_tp := high > (fixnan(Position_Price) * (1 + tp_long)) and in_longCondition
short_tp := low < (fixnan(Position_Price) * (1 - tp_short)) and in_shortCondition
last_long_tp := long_tp ? time : nz(last_long_tp[1])
last_short_tp := short_tp ? time : nz(last_short_tp[1])
Final_Long_tp := (long_tp and last_longCondition > nz(last_long_tp[1]) and last_longCondition > nz(last_long_sl[1]))
Final_Short_tp := (short_tp and last_shortCondition > nz(last_short_tp[1]) and last_shortCondition > nz(last_short_sl[1]))
L_tp = iff(Final_Long_tp, fixnan(Position_Price) * (1 + tp_long) , na)
S_tp = iff(Final_Short_tp, fixnan(Position_Price) * (1 - tp_short) , na)
//TP SIGNALS--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
tplLevel = (in_longCondition and
(last_longCondition > nz(last_long_tp[1])) and
(last_longCondition > nz(last_long_sl[1])) and not Final_Long_sl[1]) ?
(nLongs > 1) ?
(fixnan(Position_Price) * (1 + tp_long)) : (last_open_longCondition * (1 + tp_long)) : na
tpsLevel = (in_shortCondition and
(last_shortCondition > nz(last_short_tp[1])) and
(last_shortCondition > nz(last_short_sl[1])) and not Final_Short_sl[1]) ?
(nShorts > 1) ?
(fixnan(Position_Price) * (1 - tp_short)) : (last_open_shortCondition * (1 - tp_short)) : na
//SL ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Risk = sl0
Percent_Capital = 99
sl = in_longCondition ? min(sl0,(((Risk) * 100) / (Percent_Capital * max(1, nLongs)))) :
in_shortCondition ? min(sl0,(((Risk) * 100) / (Percent_Capital * max(1, nShorts)))) : sl0
Normal_long_sl = ((in_longCondition and low <= ((1 - (sl / 100)) * (fixnan(Position_Price)))))
Normal_short_sl = ((in_shortCondition and high >= ((1 + (sl / 100)) * (fixnan(Position_Price)))))
last_long_sl := Normal_long_sl ? time : nz(last_long_sl[1])
last_short_sl := Normal_short_sl ? time : nz(last_short_sl[1])
Final_Long_sl := Normal_long_sl and last_longCondition > nz(last_long_sl[1]) and last_longCondition > nz(last_long_tp[1]) and not Final_Long_tp
Final_Short_sl := Normal_short_sl and last_shortCondition > nz(last_short_sl[1]) and last_shortCondition > nz(last_short_tp[1]) and not Final_Short_tp
//RE-ENTRY ON TP-HIT-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
if Final_Long_tp or Final_Long_sl
CondIni_long := -1
sum_long := 0.0
nLongs := na
if Final_Short_tp or Final_Short_sl
CondIni_short := 1
sum_short := 0.0
nShorts := na
// Colors ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bar_color = in_longCondition ? #009688 : in_shortCondition ? #f06292 : color.orange
barcolor (color = Bar_color)
//PLOTS==============================================================================================================================================================================================================================================================================================================
plot(L_tp, title = "TP_L", style = plot.style_cross, color = color.fuchsia, linewidth = 7 )
plot(S_tp, title = "TP_S", style = plot.style_cross, color = color.fuchsia, linewidth = 7 )
//Price plots ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
plot((nLongs > 1) or (nShorts > 1) ? Position_Price : na, title = "Price", color = in_longCondition ? color.aqua : color.orange, linewidth = 2, style = plot.style_cross)
plot(tplLevel, title="Long TP ", style = plot.style_cross, color=color.fuchsia, linewidth = 1 )
plot(tpsLevel, title="Short TP ", style = plot.style_cross, color=color.fuchsia, linewidth = 1 )
//PLOTSHAPES----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
plotshape(Final_Long_tp, title="TP Long Signal", style = shape.triangledown, location=location.abovebar, color=color.red, size=size.tiny , text="TP", textcolor=color.red, transp = 0 )
plotshape(Final_Short_tp, title="TP Short Signal", style = shape.triangleup, location=location.belowbar, color=color.green, size=size.tiny , text="TP", textcolor=color.green, transp = 0 )
plotshape(longCondition, title="Long", style=shape.triangleup, location=location.belowbar, color=color.blue, size=size.tiny , transp = 0 )
plotshape(shortCondition, title="Short", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.tiny , transp = 0 )
// Backtest ==================================================================================================================================================================================================================================================================================================================================
if L_basic_condt
strategy.entry ("LONG", strategy.long )
if S_basic_condt
strategy.entry ("SHORT", strategy.short )
strategy.exit("TP_L", "LONG", profit = (abs((last_open_longCondition * (1 + tp_long)) - last_open_longCondition) / syminfo.mintick), limit = nLongs >= 1 ? strategy.position_avg_price * (1 + tp_long) : na, loss = (abs((last_open_longCondition*(1-(sl/100)))-last_open_longCondition)/syminfo.mintick))
strategy.exit("TP_S", "SHORT", profit = (abs((last_open_shortCondition * (1 - tp_short)) - last_open_shortCondition) / syminfo.mintick), limit = nShorts >= 1 ? strategy.position_avg_price*(1-(tp_short)) : na, loss = (abs((last_open_shortCondition*(1+(sl/100)))-last_open_shortCondition)/syminfo.mintick))
//By BabehDyo
```
> Detail
https://www.fmz.com/strategy/434296
> Last Modified
2023-12-05 11:03:37