
This is a quantitative trading strategy with multiple factors, which combines RSI, MACD, OBV, CCI, CMF, MFI, VWMACD and other technical indicators to implement automated stock quantitative trading. The strategy name is “Timing Strategy with Multiple Factors for Long and Short”.
The core logic of this strategy is to make judgments based on the patterns of multiple technical indicators. When multiple indicators give buy signals at the same time, buy operations will be executed.
Specifically, the indicators like RSI, MACD, OBV, CCI, CMF, MFI, VWMACD in the strategy will detect whether they show a pattern of slight downward trends while the values of the indicators themselves do not fall. If this happens, it may signify an upcoming rebound. This pattern is called “short squeeze” in the code. If multiple indicators show “short squeeze” at the same time, the final buy signal will be triggered.
In addition, the strategy also introduces the logic to judge abnormal trading volume. When price fluctuates sharply with no significant increase in trading volume, it is likely to be a false breakout. In this case, a buy signal will also be sent out.
In summary, by observing the reversal signals of multiple technical indicators and combining the abnormal judgment of trading volume, the accuracy of decision making can be improved, which is the key to the success of quantitative trading strategies.
The strategy has the following advantages:
Multiple factor model, which combines signals of 7 commonly used technical indicators, improves the accuracy of trading decisions.
Introduction of trading volume reversal signal can avoid being fooled by false breakouts and filter invalid signals.
Early detection of the timing of stock rebound by identifying slight downward patterns.
Automated Trading without manual intervention greatly reduces operating costs.
The strategy logic is simple and clear, easy to understand, modify and optimize.
There are also some risks with this strategy:
Improper combination of multiple factors may generate conflicting trading signals. The parameters of each factor need to be tested and tuned to find the optimal configuration.
Reversal trading itself carries certain risks, with the possibility of being reversed again. Stop loss points can be set to control risks.
VOLUME indicator may underperform for some stocks with low liquidity. In this case, the weight of VOLUME can be reduced or these stocks can be excluded.
The performance in live trading may deteriorate compared with that in historical backtesting. More live trading data should be accumulated for testing.
The strategy can be further optimized in the following aspects:
Add or reduce some technical indicators to find the optimal multi-factor model configuration.
Set different parameters or weights for different types of stocks so that the strategy can be more targeted.
Set dynamic stop loss, moving stop profit to lock in profits and control risks.
Combine industry, concepts and other information to select stocks to trade in specific sectors.
Introduce machine learning algorithms to achieve automatic optimization of strategy parameters.
Overall, this is a very promising quantitative trading strategy. By combining signals from multiple technical indicators and volume reversal judgments, it can effectively identify stock reversal opportunities for automated trading. With proper parameter tuning and risk control, it has the potential to achieve good returns. The idea behind the strategy is innovative and worth further research and application.
/*backtest
start: 2023-01-18 00:00:00
end: 2024-01-24 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © mkose81
//@version=5
strategy("MK future stopsuz 40 alım (Sadece Long)", overlay=true, max_bars_back=4000,use_bar_magnifier= true,pyramiding=40)
// RSI Hesaplama
rsi = ta.rsi(close, 14)
float botRSI = na
botRSI := ta.pivotlow(5, 5)
botcRSI = 0
botcRSI := botRSI ? 5 : nz(botcRSI[1]) + 1
newbotRSI = ta.pivotlow(5, 0)
emptylRSI = true
if not na(newbotRSI) and newbotRSI < low[botcRSI]
diffRSI = (newbotRSI - low[botcRSI]) / botcRSI
llineRSI = newbotRSI - diffRSI
for x = 1 to botcRSI - 1 by 1
if close[x] < llineRSI
emptylRSI := false
break
llineRSI -= diffRSI
emptylRSI
// Pozitif Uyumsuzluk Alım Sinyali - RSI
alRSI = 0
if emptylRSI and not na(newbotRSI)
if rsi[botcRSI] < rsi
alRSI := 1
// MACD Hesaplama
[macd, signal, _] = ta.macd(close, 21, 55, 8)
float botMACD = na
botMACD := ta.pivotlow(5, 5)
botcMACD = 0
botcMACD := botMACD ? 5 : nz(botcMACD[1]) + 1
newbotMACD = ta.pivotlow(5, 0)
emptylMACD = true
if not na(newbotMACD) and newbotMACD < low[botcMACD]
diffMACD = (newbotMACD - low[botcMACD]) / botcMACD
llineMACD = newbotMACD - diffMACD
for x = 1 to botcMACD - 1 by 1
if close[x] < llineMACD
emptylMACD := false
break
llineMACD -= diffMACD
emptylMACD
// Pozitif Uyumsuzluk Alım Sinyali - MACD
alMACD = 0
if emptylMACD and not na(newbotMACD)
if macd[botcMACD] < macd
alMACD := 1
// OBV Hesaplama ve Uyumsuzluk Tespiti
obv = ta.cum(ta.change(close) > 0 ? volume : ta.change(close) < 0 ? -volume : 0)
float botOBV = na
botOBV := ta.pivotlow(5, 5)
botcOBV = 0
botcOBV := botOBV ? 5 : nz(botcOBV[1]) + 1
newbotOBV = ta.pivotlow(5, 0)
emptylOBV = true
if not na(newbotOBV) and newbotOBV < obv[botcOBV]
diffOBV = (newbotOBV - obv[botcOBV]) / botcOBV
llineOBV = newbotOBV - diffOBV
for x = 1 to botcOBV - 1 by 1
if obv[x] < llineOBV
emptylOBV := false
break
llineOBV -= diffOBV
emptylOBV
// Pozitif Uyumsuzluk Alım Sinyali - OBV
alOBV = 0
if emptylOBV and not na(newbotOBV)
if obv[botcOBV] < obv
alOBV := 1
// CCI Hesaplama ve Uyumsuzluk Tespiti
cci = ta.cci(close, 20)
float botCCI = na
botCCI := ta.pivotlow(5, 5)
botcCCI = 0
botcCCI := botCCI ? 5 : nz(botcCCI[1]) + 1
newbotCCI = ta.pivotlow(5, 0)
emptylCCI = true
if not na(newbotCCI) and newbotCCI < cci[botcCCI]
diffCCI = (newbotCCI - cci[botcCCI]) / botcCCI
llineCCI = newbotCCI - diffCCI
for x = 1 to botcCCI - 1 by 1
if cci[x] < llineCCI
emptylCCI := false
break
llineCCI -= diffCCI
emptylCCI
// Pozitif Uyumsuzluk Alım Sinyali - CCI
alCCI = 0
if emptylCCI and not na(newbotCCI)
if cci[botcCCI] < cci
alCCI := 1
// CMF Hesaplama
length = 20
mfm = ((close - low) - (high - close)) / (high - low)
mfv = mfm * volume
cmf = ta.sma(mfv, length) / ta.sma(volume, length)
float botCMF = na
botCMF := ta.pivotlow(5, 5)
botcCMF = 0
botcCMF := botCMF ? 5 : nz(botcCMF[1]) + 1
newbotCMF = ta.pivotlow(5, 0)
emptylCMF = true
if not na(newbotCMF) and newbotCMF < cmf[botcCMF]
diffCMF = (newbotCMF - cmf[botcCMF]) / botcCMF
llineCMF = newbotCMF - diffCMF
for x = 1 to botcCMF - 1 by 1
if cmf[x] < llineCMF
emptylCMF := false
break
llineCMF -= diffCMF
emptylCMF
// Pozitif Uyumsuzluk Alım Sinyali - CMF
alCMF = 0
if emptylCMF and not na(newbotCMF)
if cmf[botcCMF] < cmf
alCMF := 1
// MFI Hesaplama
lengthMFI = 14
mfi = ta.mfi(close, lengthMFI)
float botMFI = na
botMFI := ta.pivotlow(mfi, 5, 5)
botcMFI = 0
botcMFI := botMFI ? 5 : nz(botcMFI[1]) + 1
newbotMFI = ta.pivotlow(mfi, 5, 0)
emptylMFI = true
if not na(newbotMFI) and newbotMFI < mfi[botcMFI]
diffMFI = (newbotMFI - mfi[botcMFI]) / botcMFI
llineMFI = newbotMFI - diffMFI
for x = 1 to botcMFI - 1 by 1
if mfi[x] < llineMFI
emptylMFI := false
break
llineMFI -= diffMFI
emptylMFI
// Pozitif Uyumsuzluk Alım Sinyali - MFI
alMFI = 0
if emptylMFI and not na(newbotMFI)
if mfi[botcMFI] < mfi
alMFI := 1
// VWMACD Hesaplama
fastLength = 12
slowLength = 26
signalSmoothing = 9
vwmacd = ta.ema(close, fastLength) - ta.ema(close, slowLength)
signalLine = ta.ema(vwmacd, signalSmoothing)
histogram = vwmacd - signalLine
// VWMACD Uyumsuzluk Tespiti
float botVWMACD = na
botVWMACD := ta.pivotlow(histogram, 5, 5)
botcVWMACD = 0
botcVWMACD := botVWMACD ? 5 : nz(botcVWMACD[1]) + 1
newbotVWMACD = ta.pivotlow(histogram, 5, 0)
emptylVWMACD = true
if not na(newbotVWMACD) and newbotVWMACD < histogram[botcVWMACD]
diffVWMACD = (newbotVWMACD - histogram[botcVWMACD]) / botcVWMACD
llineVWMACD = newbotVWMACD - diffVWMACD
for x = 1 to botcVWMACD - 1 by 1
if histogram[x] < llineVWMACD
emptylVWMACD := false
break
llineVWMACD -= diffVWMACD
emptylVWMACD
// Pozitif Uyumsuzluk Alım Sinyali - VWMACD
alVWMACD = 0
if emptylVWMACD and not na(newbotVWMACD)
if histogram[botcVWMACD] < histogram
alVWMACD := 1
//Dipci indikator
lengthd= 130
coef = 0.2
vcoef = 2.5
signalLength = 5
smoothVFI = false
ma(x, y) =>
smoothVFI ? ta.sma(x, y) : x
typical = hlc3
inter = math.log(typical) - math.log(typical[1])
vinter = ta.stdev(inter, 30)
cutoff = coef * vinter * close
vave = ta.sma(volume, lengthd)[1]
vmax = vave * vcoef
vc = volume < vmax ? volume : vmax //min( volume, vmax )
mf = typical - typical[1]
iff_4 = mf < -cutoff ? -vc : 0
vcp = mf > cutoff ? vc : iff_4
vfi = ma(math.sum(vcp, lengthd) / vave, 3)
vfima = ta.ema(vfi, signalLength)
d = vfi - vfima
// Kullanıcı girdileri
volatilityThreshold = input.float(1.005, title="Volume Percentage Threshold")
pinThreshold = input.float(1.005, title="Deep Percentage Threshold")
// Hesaplamalar
volatilityPercentage = (high - low) / open
pinPercentage = close > open ? (high - close) / open : (close - low) / open
// Volatilite koşulu ve VFI ile filtreleme
voldip = volatilityPercentage >= volatilityThreshold or pinPercentage >= pinThreshold
volCondition = voldip and vfi< 0 // VFI değeri 0'dan küçükse volCondition aktif olacak
threeCommasEntryComment = input.string(title="3Commas Entry Comment", defval="")
threeCommasExitComment = input.string(title="3Commas Exit Comment", defval="")
takeProfitPerc = input.float(1, title="Take Profit Percentage (%)") / 100
fallPerc = input.float(5, title="Percentage for Additional Buy (%)") / 100
// Değişkenlerin tanımlanması
var float lastBuyPrice = na
var float tpPrice = na
var int lastTpBar = na
// Alım koşulları
longCondition = alRSI or alMACD or alOBV or alCCI or alCMF or alMFI or alVWMACD or volCondition
// Son alım fiyatını saklamak için değişken
// İlk alım stratejisi
if (longCondition and strategy.position_size == 0)
strategy.entry("Long", strategy.long, comment=threeCommasEntryComment)
lastBuyPrice := open
// İkinci ve sonraki alım koşulları (son alım fiyatının belirlenen yüzde altında)
if (open < lastBuyPrice * (1 - fallPerc) and strategy.position_size > 0)
strategy.entry("Long Add", strategy.long, comment=threeCommasEntryComment)
lastBuyPrice := open
// Kar alma fiyatını hesaplama ve strateji çıkışı
tp_price = strategy.position_avg_price * (1 + takeProfitPerc)
if strategy.position_size > 0
strategy.exit("Exit Long", "Long", limit=tp_price, comment=threeCommasExitComment)
strategy.exit("Exit Long Add", "Long Add", limit=tp_price, comment=threeCommasExitComment)
tpPrice := na // Pozisyon kapandığında TP çizgisini sıfırla
// Kar alma seviyesi çizgisi çizme
plot(strategy.position_size > 0 ? tp_price : na, color=color.green, title="Take Profit Line")