改良型渔网策略
该策略对经典的渔网策略进行了改进,加入了买卖信号阈值、移动止损等功能,形成较为完整的趋势追踪体系。
渔网策略通过计算价格的力度中心来判断市场趋势,力度中心反映了价格和成交量的关系。当力度中心上升时表示多头力量增强,下降时表示空头力量增强,因此可以据此产生交易信号。
计算力度中心的关键在于价格与时间的关系。简单来说,最近发生的价格变动影响趋势判断的权重更大,久远的价格变动权重更小。因此计算时,乘以一个随时间衰减的权重。这样高位发生的交易对总体判断影响更大。
但原始的渔网策略只根据力度中心曲线的方向判断多空,很容易在横盘时被套牢。这次改进加入了确定的买卖信号阈值,只有在力度中心超过一定幅度时才发出信号,这样可以过滤掉许多噪音信号。
此外,改进版本实现了移动止损和固定止损相结合的出场机制。进入趋势后,移动止损可以随行情的推移不断调整,实现流动的风险控制。而固定止损则可以更加可靠地防止突发事件造成的损失。
当然,力度中心指标对复杂行情的判断力较弱,移动止损在设定不当时也可能被突破,这需要交易者保持警惕,适时优化参数。但总的来说,这套改进型渔网策略机制更加完备,可以产生较好的稳定收益。
/*backtest
start: 2023-09-04 00:00:00
end: 2023-09-11 00:00:00
period: 30m
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=3
// Copyright nilux: https://www.tradingview.com/u/nilux/
// Based on the original of dasanc: https://www.tradingview.com/u/dasanc/
strategy("FSCG-TSSL", "FSCG-TSSL Mod Backtest", default_qty_type = strategy.percent_of_equity, default_qty_value = 100, initial_capital = 100000, slippage = 5)
Price = input.source(close, "Source")
Length = input(20,"Period")
transform = input("Inphase-Quadrature","Use Transform?",options=["Hilbert","Inphase-Quadrature","False"])
min = input(108,"Min. Period")
buyTreshold = input(-2.41, title = "Buy Treshold (-)", type = float, defval=-2.0, minval = -2.50, maxval = -0.01, step = 0.01)
sellTreshold = input(2.43, title = "Sell Treshold (+)", type = float, defval=2.0, minval = 0.01, maxval = 2.50, step = 0.01)
// === TSSL ===
fixedSL = input(title="SL Activation", defval=300)
trailSL = input(title="SL Trigger", defval=1)
fixedTP = input(title="TP Activation", defval=150)
trailTP = input(title="TP Trigger", defval=50)
// === BACKTEST RANGE ===
FromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
FromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromYear = input(defval = 2019, title = "From Year", minval = 2015)
ToMonth = input(defval = 1, title = "To Month", minval = 1, maxval = 12)
ToDay = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToYear = input(defval = 9999, title = "To Year", minval = 2015)
start = timestamp(FromYear, FromMonth, FromDay, 00, 00)
finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)
window() => time >= start and time <= finish ? true : false
getIQ(src,min,max) =>
PI = 3.14159265359
P = src - src[7]
lenIQ = 0.0
lenC = 0.0
imult = 0.635
qmult = 0.338
inphase = 0.0
quadrature = 0.0
re = 0.0
im = 0.0
deltaIQ = 0.0
instIQ = 0.0
V = 0.0
inphase := 1.25*(P[4] - imult*P[2]) + imult*nz(inphase[3])
quadrature := P[2] - qmult*P + qmult*nz(quadrature[2])
re := 0.2*(inphase*inphase[1] + quadrature*quadrature[1]) + 0.8*nz(re[1])
im := 0.2*(inphase*quadrature[1] - inphase[1]*quadrature) + 0.8*nz(im[1])
if (re!= 0.0)
deltaIQ := atan(im/re)
for i=0 to max
V := V + deltaIQ[i]
if (V > 2*PI and instIQ == 0.0)
instIQ := i
if (instIQ == 0.0)
instIQ := nz(instIQ[1])
lenIQ := 0.25*instIQ + 0.75*nz(lenIQ[1],1)
length = lenIQ<min ? min : lenIQ
getHT(src) =>
Price = src
Imult = .635
Qmult = .338
PI = 3.14159
InPhase = 0.0
Quadrature = 0.0
Phase = 0.0
DeltaPhase = 0.0
InstPeriod = 0.0
Period = 0.0
Value4 = 0.0
if(n > 5)
//Detrend Price
Value3 = Price - Price[7]
//Compute InPhase and Quadrature components
InPhase := 1.25*(Value3[4] - Imult*Value3[2]) + Imult*nz(InPhase[3])
Quadrature := Value3[2] - Qmult*Value3 + Qmult*nz(Quadrature[2])
//Use ArcTangent to compute the current phase
if(abs(InPhase + InPhase[1]) > 0)
Phase := 180/PI * atan(abs((Quadrature + Quadrature[1]) / (InPhase + InPhase[1])))
//Resolve the ArcTangent ambiguity
if(InPhase < 0 and Quadrature > 0)
Phase := 180 - Phase
if(InPhase < 0 and Quadrature < 0)
Phase := 180 + Phase
if(InPhase > 0 and Quadrature < 0)
Phase := 360 - Phase
//Compute a differential phase, resolve phase wraparound, and limit delta phase errors
DeltaPhase := Phase[1] - Phase
if(Phase[1] < 90 and Phase > 270)
DeltaPhase := 360 + Phase[1] - Phase
if(DeltaPhase < 1)
DeltaPhase := 1
if(DeltaPhase > 60)
DeltaPhase := 60
//Sum DeltaPhases to reach 360 degrees. The sum is the instantaneous period.
for i = 0 to 50
Value4 := Value4 + DeltaPhase[i]
if(Value4 > 360 and InstPeriod == 0)
InstPeriod := i
//Resolve Instantaneous Period errors and smooth
if(InstPeriod == 0)
InstPeriod = nz(InstPeriod[1])
Period := .25*(InstPeriod) + .75*Period[1]
Period
//Get highest val in period
getHighest(src, len)=>
H = src[len]
for i=0 to len
if src[i]>H
H := src[i]
H
//Get lowest val in period
getLowest(src, len)=>
L = src[len]
for i=0 to len
if src[i]<L
L := src[i]
L
if transform == "Hilbert"
Length := round(getHT(Price)/2)
if transform == "Inphase-Quadrature"
Length := round(getIQ(Price,min,50)/2)
if Length<min
Length := min
Num = 0.0
Denom = 0.0
CG = 0.0
MaxCG = 0.0
MinCG = 0.0
Value1 = 0.0
Value2 = 0.0
Value3 = 0.0
for i = 0 to Length - 1
Num := Num + (1 + i)*(Price[i])
Denom := Denom + (Price[i])
if(Denom != 0)
CG := -Num/Denom + (Length + 1) / 2
MaxCG := getHighest(CG, Length)
MinCG := getLowest(CG, Length)
if(MaxCG != MinCG)
Value1 := (CG - MinCG) / (MaxCG - MinCG)
Value2 := (4*Value1 + 3*Value1[1] + 2*Value1[2] + Value1[3]) / 10
Value3 := .5*log((1+1.98*(Value2-.5))/(1-1.98*(Value2-.5)))
plot(Value3, "CG",orange, linewidth=2)
plot(Value3[1], "Trigger",green, linewidth=2)
hline(0,color=color(black,60))
hline(2,linestyle=hline.style_solid,color=color(black,70))
hline(-2,linestyle=hline.style_solid,color=color(black,70))
sell = crossover(Value3[1],Value3) and Value3 > sellTreshold
buy = crossunder(Value3[1],Value3) and Value3 < buyTreshold
strategy.entry("Long", strategy.long, when= buy and window())
strategy.exit("Exit", loss=fixedSL, trail_offset=trailTP, trail_points=fixedTP)
strategy.exit("Exit", when= sell)
strategy.entry("Short", strategy.short, when= sell and window())
strategy.exit("Exit", loss=fixedSL, trail_offset=trailTP, trail_points=fixedTP)
strategy.exit("Exit", when= buy)