
漸進的要素重量DCA定量取引戦略は,移動平均指標のトリガー信号と漸進的重量ドルコストアベアジングの仕組みを組み合わせた定量取引戦略である.この戦略は,トレンド判断とコストの均等な方法で,トレンド方向性の強い市場でより安定した収益を得ることを目的としている.
この戦略は主に3つの部分から構成されています.
早い移動平均と遅い移動平均の交差を入場判断の信号として使用する. SMA,EMAまたはHMAを遅い平均線として選択できる. 早い平均線が下の方から遅い平均線を突破すると,買いの信号が生じる. 早い平均線が上の方から遅い平均線を突破すると,売りの信号が生じる.
買取シグナルがトリガーされた後,戦略は直ちにポジションを開き,基礎ポジションを確立する.その後,価格が下がり続けると,戦略は漸進的な加重方式で,後続のセキュリティポジションを増加させる.新しいセキュリティポジションの価格は,前のセキュリティポジションの価格を参考にして一定幅の下落を順次行なう.同時に,新しいセキュリティポジションの資金量は順次増加する.
順次加仓することで,ある程度コストの均等化を実現し,取引リスクの管理を保証しながら,優良なコスト価格を得ることができる.
価格が上昇してストップラインを突破すると,ストップを選択し,価格が下がってストップラインを突破すると,ストップを選択します.
ストップラインは,ベースポジションの取引平均価格の1+固定比率として固定されます.
ストップラインは,最後の安全なポジションの価格の変動である. 最後の安全なポジションの取引価格の下にある一定割合でストップシグナルを確認する.
トレンド判断は,方向性のない揺れ動いている市場を回避し,コストの対価は,トレンドの中で優越したコストを得ることができます.
均衡したポジションの規模には一定の幅度があり,その後のポジションには一定の撤回要求があり,リスクを制御できます.
コードにリアルタイムモニタリングのタグが加えられ,戦略の占拠額の上限を明確に知ることができ,ポジションの平準化につながる過剰使用を防ぐことができます.
ベースポジションとセーフティーポジションは,それぞれストップ・ロスを止め,利益を終了し,リスクを制御する.
価格が激しく揺れると,複数の加仓を誘発して損失を増加させる可能性があります. 後の安全ポジション間での取り戻しの要求を適切に増やすことによって加仓の回数を減らすことができます.
平均線パラメータは,入場タイミングに直接影響し,異なる品種は,適切なパラメータを決定するためにテストを必要とします.
ストップ・ストップ・スロープ比率は,リターン率と撤回制御に関連しており,フィットネス・データによる最適化設定が必要である.
最大の撤回または値を超えたポジション保持時間の強制平仓条件をテストして,さらにリスクを制御することができる.
漸進的要素加重のDCA量化取引戦略は,トレンド判断とコストの均衡の優位性を統合し,強いトレンドの状況で安定した収益を得ることができます.最適化パラメータ設定,ポジションサイズとポジション間引き戻しの要求を調整することにより,リスクが制御可能な安定した取引を実現できます.この戦略は,ヘッジファンド,CTAファンド,およびいくつかの対抗策の設計に適用できます.
/*backtest
start: 2022-11-09 00:00:00
end: 2023-11-15 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/
// © MGTG
//@version=5
Strategy = input.string('Long', options=['Long'], group='Strategy', inline='1',
tooltip='Long bots profit when asset prices rise, Short bots profit when asset prices fall'
+ '\n\n' + 'Please note: to run a Short bot on a spot exchange account, you need to own the asset you want to trade. The bot will sell the asset at the current chart price and buy it back at a lower price - the profit made is actually trapped equity released from an asset you own that is declining in value.')
Profit_currency = input.string('Quote (USDT)', 'Profit currency', options=['Quote (USDT)', 'Quote (BTC)', 'Quote (BUSD)'], group='Strategy', inline='1')
Base_order_size = input.int(10, 'Base order Size', group='Strategy', inline='2',
tooltip='The Base Order is the first order the bot will create when starting a new deal.')
Safety_order_size = input.int(20, 'Safety order Size', group='Strategy', inline='2',
tooltip="Enter the amount of funds your Safety Orders will use to Average the cost of the asset being traded, this can help your bot to close deals faster with more profit. Safety Orders are also known as Dollar Cost Averaging and help when prices moves in the opposite direction to your bot's take profit target.")
Triger_Type = input.string('Over', 'Entry at Cross Over / Under', options=['Over', 'Under'], group='Deal start condition > Trading View custom signal', inline='1',
tooltip='Deal start condition decision')
Short_Moving_Average = input.string('SMA', 'Short Moving Average', group='Deal start condition > Trading View custom signal', inline='2',
options=["SMA", "EMA", "HMA"])
Short_Period = input.int(5, 'Period', group='Deal start condition > Trading View custom signal', inline='2')
Long_Moving_Average = input.string('HMA', 'Long Moving Average', group='Deal start condition > Trading View custom signal', inline='3',
options=["SMA", "EMA", "HMA"])
Long_Period = input.int(50, 'Period', group='Deal start condition > Trading View custom signal', inline='3')
Target_profit = input.float(1.5, 'Target profit (%)', step=0.05, group='Take profit / Stop Loss', inline='1') * 0.01
Stop_Loss = input.int(15, 'Stop Loss (%)', group='Take profit / Stop Loss', inline='1',
tooltip='This is the percentage that price needs to move in the opposite direction to your take profit target, at which point the bot will execute a Market Order on the exchange account to close the deal for a smaller loss than keeping the deal open.'
+ '\n' + 'Please note, the Stop Loss is calculated from the price the Safety Order at on the exchange account and not the Dollar Cost Average price.') * 0.01
Max_safety_trades_count = input.int(10, 'Max safety trades count', maxval=10, group='Safety orders', inline='1')
Price_deviation = input.float(0.4, 'Price deviation to open safety orders (% from initial order)', step=0.01, group='Safety orders', inline='2') * 0.01
Safety_order_volume_scale = input.float(1.8, 'Safety order volume scale', step=0.01, group='Safety orders', inline='3')
Safety_order_step_scale = input.float(1.19, 'Safety order step scale', step=0.01, group='Safety orders', inline='3')
// daily_volume = input.int(500, "Don't start deal(s) if the daily volume is less than", group='Advanced settings', inline='1')
// Minimum_price = input.int(500, "Minimum price to open deal", group='Advanced settings', inline='1')
// Maximum_price = input.int(500, "Maximum price to open deal", group='Advanced settings', inline='1')
// Close_deal_after_timeout = input.int(5, "Close deal after timeout (Hrs)", group='Advanced settings', inline='1')
initial_capital = 8913
strategy(
title='3Commas Visible DCA Strategy',
overlay=true,
initial_capital=initial_capital,
pyramiding=11,
process_orders_on_close=true,
commission_type=strategy.commission.percent,
commission_value=0.01,
max_bars_back=5000,
max_labels_count=50)
// Position
status_none = strategy.position_size == 0
status_long = strategy.position_size[1] == 0 and strategy.position_size > 0
status_long_offset = strategy.position_size[2] == 0 and strategy.position_size[1] > 0
status_short = strategy.position_size[1] == 0 and strategy.position_size < 0
status_increase = strategy.opentrades[1] < strategy.opentrades
Short_Moving_Average_Line =
Short_Moving_Average == 'SMA' ? ta.sma(close, Short_Period) :
Short_Moving_Average == 'EMA' ? ta.ema(close, Short_Period) :
Short_Moving_Average == 'HMA' ? ta.sma(close, Short_Period) : na
Long_Moving_Average_Line =
Long_Moving_Average == 'SMA' ? ta.sma(close, Long_Period) :
Long_Moving_Average == 'EMA' ? ta.ema(close, Long_Period) :
Long_Moving_Average == 'HMA' ? ta.sma(close, Long_Period) : na
Base_order_Condition = Triger_Type == "Over" ? ta.crossover(Short_Moving_Average_Line, Long_Moving_Average_Line) : ta.crossunder(Short_Moving_Average_Line, Long_Moving_Average_Line) // Buy when close crossing lower band
safety_order_deviation(index) => Price_deviation * math.pow(Safety_order_step_scale, index - 1)
pd = Price_deviation
ss = Safety_order_step_scale
step(i) =>
i == 1 ? pd :
i == 2 ? pd + pd * ss :
i == 3 ? pd + (pd + pd * ss) * ss :
i == 4 ? pd + (pd + (pd + pd * ss) * ss) * ss :
i == 5 ? pd + (pd + (pd + (pd + pd * ss) * ss) * ss) * ss :
i == 6 ? pd + (pd + (pd + (pd + (pd + pd * ss) * ss) * ss) * ss) * ss :
i == 7 ? pd + (pd + (pd + (pd + (pd + (pd + pd * ss) * ss) * ss) * ss) * ss) * ss :
i == 8 ? pd + (pd + (pd + (pd + (pd + (pd + (pd + pd * ss) * ss) * ss) * ss) * ss) * ss) * ss :
i == 9 ? pd + (pd + (pd + (pd + (pd + (pd + (pd + (pd + pd * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss :
i == 10 ? pd + (pd + (pd + (pd + (pd + (pd + (pd + (pd + (pd + pd * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss) * ss : na
long_line(i) =>
close[1] - close[1] * (step(i))
Safe_order_line(i) =>
i == 0 ? ta.valuewhen(status_long, long_line(0), 0) :
i == 1 ? ta.valuewhen(status_long, long_line(1), 0) :
i == 2 ? ta.valuewhen(status_long, long_line(2), 0) :
i == 3 ? ta.valuewhen(status_long, long_line(3), 0) :
i == 4 ? ta.valuewhen(status_long, long_line(4), 0) :
i == 5 ? ta.valuewhen(status_long, long_line(5), 0) :
i == 6 ? ta.valuewhen(status_long, long_line(6), 0) :
i == 7 ? ta.valuewhen(status_long, long_line(7), 0) :
i == 8 ? ta.valuewhen(status_long, long_line(8), 0) :
i == 9 ? ta.valuewhen(status_long, long_line(9), 0) :
i == 10 ? ta.valuewhen(status_long, long_line(10), 0) : na
TP_line = strategy.position_avg_price * (1 + Target_profit)
SL_line = Safe_order_line(Max_safety_trades_count) * (1 - Stop_Loss)
safety_order_size(i) => Safety_order_size * math.pow(Safety_order_volume_scale, i - 1)
plot(Short_Moving_Average_Line, 'Short MA', color=color.new(color.white, 0), style=plot.style_line)
plot(Long_Moving_Average_Line, 'Long MA', color=color.new(color.green, 0), style=plot.style_line)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 1 ? Safe_order_line(1) : na, 'Safety order1', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 2 ? Safe_order_line(2) : na, 'Safety order2', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 3 ? Safe_order_line(3) : na, 'Safety order3', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 4 ? Safe_order_line(4) : na, 'Safety order4', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 5 ? Safe_order_line(5) : na, 'Safety order5', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 6 ? Safe_order_line(6) : na, 'Safety order6', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 7 ? Safe_order_line(7) : na, 'Safety order7', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 8 ? Safe_order_line(8) : na, 'Safety order8', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 9 ? Safe_order_line(9) : na, 'Safety order9', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 and Max_safety_trades_count >= 10 ? Safe_order_line(10) : na, 'Safety order10', color=color.new(#009688, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 ? TP_line : na, 'Take Profit', color=color.new(color.orange, 0), style=plot.style_linebr)
plot(strategy.position_size > 0 ? SL_line : na, 'Safety', color=color.new(color.aqua, 0), style=plot.style_linebr)
currency =
Profit_currency == 'Quote (USDT)' ? ' USDT' :
Profit_currency == 'Quote (BTC)' ? ' BTC' :
Profit_currency == 'Quote (BUSD)' ? ' BUSD' : na
if Base_order_Condition
strategy.entry('Base order', strategy.long, qty=Base_order_size/close, when=Base_order_Condition and strategy.opentrades == 0,
comment='BO' + ' - ' + str.tostring(Base_order_size) + str.tostring(currency))
for i = 1 to Max_safety_trades_count by 1
i_s = str.tostring(i)
strategy.entry('Safety order' + i_s, strategy.long, qty=safety_order_size(i)/close,
limit=Safe_order_line(i), when=(strategy.opentrades <= i) and strategy.position_size > 0,
comment='SO' + i_s + ' - ' + str.tostring(safety_order_size(i)) + str.tostring(currency))
for i = 1 to Max_safety_trades_count by 1
i_s = str.tostring(i)
// strategy.close('Base order', when=shortCondition)
// strategy.close('Safety order' + i_s, when=shortCondition)
// strategy.cancel('Safety order' + i_s, when=shortCondition)
strategy.cancel('SO' + i_s, when=ta.crossunder(low, SL_line) or ta.crossover(high, TP_line) or status_none)
strategy.exit('TP/SL','Base order', limit=TP_line, stop=SL_line, comment = Safe_order_line(100) > close ? 'SL' + i_s + ' - ' + str.tostring(Base_order_size) + str.tostring(currency) : 'TP' + i_s + ' - ' + str.tostring(Base_order_size) + str.tostring(currency))
strategy.exit('TP/SL','Safety order' + i_s, limit=TP_line, stop=SL_line, comment = Safe_order_line(100) > close ? 'SL' + i_s + ' - ' + str.tostring(safety_order_size(i)) + str.tostring(currency) : 'TP' + i_s + ' - ' + str.tostring(safety_order_size(i)) + str.tostring(currency))
// strategy.cancel('TP/SP' + i_s, when=Base_order_Condition)
// strategy.exit('Stop Loss','Base order', stop=SL_line)
// strategy.exit('Stop Loss','Safety order' + i_s, stop=SL_line)
//----------------label A----------------//
bot_usage(i) =>
i == 1 ? Base_order_size + safety_order_size(1) :
i == 2 ? Base_order_size + safety_order_size(1) + safety_order_size(2) :
i == 3 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) :
i == 4 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) + safety_order_size(4) :
i == 5 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) + safety_order_size(4) + safety_order_size(5) :
i == 6 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) + safety_order_size(4) + safety_order_size(5) + safety_order_size(6) :
i == 7 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) + safety_order_size(4) + safety_order_size(5) + safety_order_size(6) + safety_order_size(7) :
i == 8 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) + safety_order_size(4) + safety_order_size(5) + safety_order_size(6) + safety_order_size(7) + safety_order_size(8) :
i == 9 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) + safety_order_size(4) + safety_order_size(5) + safety_order_size(6) + safety_order_size(7) + safety_order_size(8) + safety_order_size(9) :
i == 10 ? Base_order_size + safety_order_size(1) + safety_order_size(2) + safety_order_size(3) + safety_order_size(4) + safety_order_size(5) + safety_order_size(6) + safety_order_size(7) + safety_order_size(8) + safety_order_size(9) + safety_order_size(10) : na
equity = strategy.equity
bot_use = bot_usage(Max_safety_trades_count)
bot_dev = float(step(Max_safety_trades_count)) * 100
bot_ava = (bot_use / equity) * 100
string label_A =
'Balance : ' + str.tostring(math.round(equity, 0), '###,###,###,###') + ' USDT' + '\n' +
'Max amount for bot usage : ' + str.tostring(math.round(bot_use, 0), '###,###,###,###') + ' USDT' + '\n' +
'Max safety order price deviation : ' + str.tostring(math.round(bot_dev, 0), '##.##') + ' %' + '\n' +
'% of available balance : ' + str.tostring(math.round(bot_ava, 0), '###,###,###,###') + ' %'
+ (bot_ava > 100 ? '\n \n' + '⚠ Warning! Bot will use amount greater than you have on exchange' : na)
if status_long
day_label =
label.new(
x=time[1],
y=high * 1.03,
text=label_A,
xloc=xloc.bar_time,
yloc=yloc.price,
color=bot_ava > 100 ? color.new(color.yellow, 0) : color.new(color.black, 50),
style=label.style_label_lower_right,
textcolor=bot_ava > 100 ? color.new(color.red, 0) : color.new(color.silver, 0),
size=size.normal,
textalign=text.align_left)