K-line을 기반으로 한 양방향 돌파거래 전략


생성 날짜: 2024-01-30 17:27:01 마지막으로 수정됨: 2024-01-30 17:27:01
복사: 4 클릭수: 647
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

K-line을 기반으로 한 양방향 돌파거래 전략

개요

이것은 K선에 기반한 양방향의 돌파 거래 전략이다. K선 종결 가격과 비교하여 K선 앞의 최고 가격과 최저 가격이 모두 돌파되었을 때 거래 신호를 발생시킨다.

전략 원칙

이 전략의 기본 논리는 다음과 같습니다.

  1. 황소 신호의 정의:bull = close > open and close > math.max(close[2], open[2]) and low[1] < low[2] and high[1] < high[2]즉, 현재 K 선의 종료 가격은 오픈 가격보다 크고, 이전 두 K 선의 최고 가격보다 크며, 현재 K 선의 최저 가격은 이전 한 K 선의 최저 가격보다 낮습니다.

  2. 곰의 신호를 정의합니다.bear = close < open and close < math.min(close[2], open[2]) and low[1] > low[2] and high[1] > high[2]즉, 현재 K 선의 종료 가격은 개장 가격보다 작고, 이전 두 K 선의 최저 가격보다 작으며, 현재 K 선의 최고 가격은 이전 한 K 선의 최고 가격보다 높습니다.

  3. 황소 신호를 쏘면 더 하고, 곰 신호를 쏘면 공백을 하라.

  4. 스톱로스트와 스톱스톱을 설정할 수 있다.

이 전략은 양방향의 브레이크 특성을 활용하여 중요한 가격 범위를 돌파하여 트렌드 변화를 판단하여 거래 신호를 생성합니다.

우위 분석

이것은 비교적 간단하고 직관적인 돌파구 전략으로 다음과 같은 장점이 있습니다.

  1. 논리적으로 명확하고, 이해하기 쉽고, 실행 가능하며, 관점은 높지 않습니다.

  2. 브레이크는 일반적인 거래 신호이며, 트렌드를 형성하기 쉽다.

  3. 동시에 더 많은 코스피를 취해 양방향 거래로 수익을 올릴 수 있습니다.

  4. 유연하게 HST를 설정하여 위험을 제어할 수 있습니다.

위험 분석

이 전략에는 몇 가지 위험도 있습니다.

  1. 이중 거래는 위험성이 높고, 철저한 감시가 필요합니다.

  2. 은 은 은 은 은

  3. 잘못된 매개 변수 설정으로 인해 과도한 거래가 발생할 수 있습니다.

  4. 스티커를 잘못 설정하면 수익률이 떨어지기도 한다.

그 결과, 이 종의 개체수와 개체군에 대한 위험성을 줄일 수 있는 적절한 선택이 가능해졌다.

최적화 방향

이 전략은 다음과 같은 부분에서 최적화될 수 있습니다.

  1. 최적화 매개 변수, 예를 들어, 브레이크 사이클 매개 변수, 스로스 스톱 幅 등.

  2. 필터링 조건을 추가하여 중고, 흔들림 등의 잘못된 신호를 방지합니다.

  3. 트렌드 지표와 결합하여 상쇄 범위를 피하십시오.

  4. 자금 관리를 최적화하고, 포지션 알고리즘을 개선한다.

  5. 다양한 품종의 파라미터는 다르며, 개별적으로 테스트 최적화를 할 수 있다.

요약하다

이것은 양방향의 돌파구 사고에 기반한 간단한 전략이다. 논리적으로 명확하고 쉽게 구현할 수 있는 장점이 있지만, 또한 일정량의 감시 위험도 존재한다. 매개 변수 및 조건 최적화를 통해 더 나은 전략 효과를 얻을 수 있다.

전략 소스 코드
/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5

// # ========================================================================= #
// #                   |   Strategy  |
// # ========================================================================= #

SystemName = "Strategy Template Autoview"
TradeId = "S"
// These values are used both in the strategy() header and in the script's relevant inputs as default values so they match.
// Unless these values match in the script's Inputs and the TV backtesting Properties, results between them cannot be compared.
InitCapital = 1000000
InitPosition = 2
InitCommission = 0.075
InitPyramidMax = 1
CalcOnorderFills = false
ProcessOrdersOnClose = true // display the signals one candle earlier
CalcOnEveryTick = true // forward testing
//CloseEntriesRule = "ANY"

strategy(title=SystemName, shorttitle=SystemName, 
 overlay=true, pyramiding=InitPyramidMax, initial_capital=InitCapital, default_qty_type=strategy.fixed, process_orders_on_close=ProcessOrdersOnClose,
 default_qty_value=InitPosition, commission_type=strategy.commission.percent, commission_value=InitCommission, calc_on_order_fills=CalcOnorderFills, 
 calc_on_every_tick=CalcOnEveryTick, 
 precision=6, max_lines_count=500, max_labels_count=500)

// # ========================================================================= #
// # ========================================================================= #
// #                   ||   Alerts  ||
// # ========================================================================= #
// # ========================================================================= #

show_alerts_debug = input.bool(true, title = "Show Alerts Debug Label?", group = "Debug")

//i_alert_txt_entry_long = input.text_area(defval = "", title = "Long Entry Message", group = "Alerts")
//i_alert_txt_entry_short = input.text_area(defval = "", title = "Short Entry Message", group = "Alerts")
//i_alert_txt_exit_long = input.text_area(defval = "", title = "Long Exit Message", group = "Alerts")
//i_alert_txt_exit_short = input.text_area(defval = "", title = "Short Exit Message", group = "Alerts")

i_broker_mode = input.string("DEMO", title = "Use Demo or Live Broker", options=["DEMO", "LIVE"], group = "Automation")
i_broker_name = input.string("Tradovate", title = "Broker Name", options=["Tradovate", "AscendEX", "Binance", "Binance Futures", "Binance US", "Binance Delivery", "Kraken", "Deribit", "Poloniex", "Okcoin", "Bitfinex", "Oanda", "Kucoin", "Okex", "Bybit", "FTX", "Bitmex", "Alpaca", "Gemini"], group = "Automation")

i_enable_trades = input.bool(true, title = "Enable trades?", group = "Automation", tooltip = "If not enabled, disables live trades, but more importantly, it will output what Autoview is going to do when you go live.")

i_account_name = input.string("*", title = "Account Name", group = "Automation")
i_symbol_name  = input.string("btcusd_perp", title = "Symbol Name", group = "Automation")
nb_contracts = input.int(2, title = "Nb Contracts", group = "Automation")

use_delay = input.bool(false, title = "Use Delay between orders", group = "Automation", inline = "delay")
i_delay_qty = input.int(1, title = "Delay in seconds", group = "Automation", inline = "delay")

i_use_borrow_repay   = input.bool(false, title = "Use Borrow/Repay Mode?", group = "Binance Automation")
i_asset_borrow_repay = input.string("BTC", title = "Asset to Borrow/Repay", group = "Binance Automation")
i_qty_borrow_repay   = input.float(1., title = "Quantity of assets to borrow?", group = "Binance Automation")

// # ========================================================================= #
// # ========================================================================= #
// #                   ||   Dates Range Filtering  ||
// # ========================================================================= #
// # ========================================================================= #

DateFilter = input(false, "Date Range Filtering", group="Date")

// ————— Syntax coming from https://www.tradingview.com/blog/en/new-parameter-for-date-input-added-to-pine-21812/
i_startTime = input(defval = timestamp("01 Jan 2019 13:30 +0000"), title = "Start Time", group="Date")
i_endTime = input(defval = timestamp("30 Dec 2021 23:30 +0000"), title = "End Time", group="Date")

TradeDateIsAllowed() => true


// # ========================================================================= #
// #                   |   Custom Exits |
// # ========================================================================= #

//use_custom_exit = input.bool(true, title = "Use Custom Exits?", group = "Custom Exits")

// # ========================================================================= #
// #                   |   Stop Loss |
// # ========================================================================= #

use_sl        = input.string("None", title = "Select Stop Loss Mode", options=["None", "Percent", "Price"], group = "Stop Loss")
sl_input_perc = input.float(3, minval = 0, title = "Stop Loss (%)", group = "Stop Loss (%)") * 0.01
sl_input_pips = input.float(30, minval = 0, title = "Stop Loss (USD)", group = "Stop Loss (USD)")

// # ========================================================================= #
// #                   |   Take Profit |
// # ========================================================================= #

use_tp       = input.string("None", title = "Select Take Profit Mode", options=["None", "Percent", "Price"], group = "Take Profit")
tp_input_perc = input.float(3, minval = 0, title = "Take Profit (%)", group = "Take Profit (%)") * 0.01
tp_input_pips = input.float(30, minval = 0, title = "Take Profit (USD)", group = "Take Profit (USD)")


// # ========================================================================= #
// #                   |   Consolidated Entries |
// # ========================================================================= #

bull = close > open and close > math.max(close[2], open[2]) and low[1] < low[2] and high[1] < high[2] // low < low[1] and low[1] < low[2] 
bear = close < open and close < math.min(close[2], open[2]) and low[1] > low[2] and high[1] > high[2] // low < low[1] and low[1] < low[2] 

// # ========================================================================= #
// #       |   Entry Price |
// # ========================================================================= #

entry_long_price  = ta.valuewhen(condition=bull and strategy.position_size[1] <= 0, source=close, occurrence=0)
entry_short_price = ta.valuewhen(condition=bear and strategy.position_size[1] >= 0, source=close, occurrence=0)

var float entry_price = 0.

if bull
    entry_price := entry_long_price
if bear
    entry_price := entry_short_price

// # ========================================================================= #
// #                   ||   Global Trend Variables ||
// # ========================================================================= #

T1_sinceUP = ta.barssince(bull)
T1_sinceDN = ta.barssince(bear)

T1_nUP = ta.crossunder(T1_sinceUP,T1_sinceDN)
T1_nDN = ta.crossover(T1_sinceUP,T1_sinceDN)

T1_sinceNUP = ta.barssince(T1_nUP)
T1_sinceNDN = ta.barssince(T1_nDN)

T1_BuyTrend  = T1_sinceDN > T1_sinceUP
T1_SellTrend = T1_sinceDN < T1_sinceUP

T1_SellToBuy   = T1_BuyTrend and T1_SellTrend[1]
T1_BuyToSell   = T1_SellTrend and T1_BuyTrend[1]
T1_ChangeTrend = T1_BuyToSell or T1_SellToBuy

// # ========================================================================= #
// #                   |   Stop Loss |
// # ========================================================================= #

var float final_SL_Long  = 0.
var float final_SL_Short = 0.

if use_sl == "Percent"
    final_SL_Long := entry_long_price * (1 - sl_input_perc)
    final_SL_Short := entry_short_price * (1 + sl_input_perc)
else if use_sl == "Price"
    final_SL_Long := entry_long_price - (sl_input_pips)
    final_SL_Short := entry_short_price + (sl_input_pips)

plot(strategy.position_size > 0 and use_sl != "None" ? final_SL_Long : na, title = "SL Long", color = color.fuchsia, linewidth=2, style=plot.style_linebr)
plot(strategy.position_size < 0 and use_sl != "None" ? final_SL_Short : na, title = "SL Short", color = color.fuchsia, linewidth=2, style=plot.style_linebr)

// # ========================================================================= #
// #                   |   Take Profit |
// # ========================================================================= #

var float final_TP_Long  = 0.
var float final_TP_Short = 0.

if use_tp == "Percent"
    final_TP_Long := entry_long_price   * (1 + tp_input_perc)
    final_TP_Short := entry_short_price * (1 - tp_input_perc)
else if use_tp == "Price"
    final_TP_Long := entry_long_price   + (tp_input_pips)
    final_TP_Short := entry_short_price - (tp_input_pips)

plot(strategy.position_size > 0 and use_tp != "None" ? final_TP_Long : na, title = "TP Long", color = color.orange, linewidth=2, style=plot.style_linebr)
plot(strategy.position_size < 0 and use_tp != "None" ? final_TP_Short : na, title = "TP Short", color = color.orange, linewidth=2, style=plot.style_linebr)

// # ========================================================================= #
// #                   |   AutoView Calls |
// # ========================================================================= #

float quantity = nb_contracts

string product_type_ticker = i_symbol_name

var string broker_mode = ""

if i_broker_mode == "DEMO"

    broker_mode := switch i_broker_name
        "Tradovate" => "tradovatesim"
        "Ascendex"  => "ascendex-sandbox"
        "Binance Futures" => "binancefuturestestnet"
        "Binance Delivery" => "binancedeliverytestnet"
        "Oanda" => "oandapractice"
        "Bitmex" => "bitmextestnet"
        "Bybit" => "bybittestnet"
        "Alpaca" => "alpacapaper"
        "Kucoin" => "kucoinsandbox"
        "Deribit" => "deribittestnet"
        "Gemini" => "gemini-sandbox"
        => i_broker_name

else // "LIVE"

    broker_mode := switch i_broker_name
        "Tradovate" => "tradovate"
        "Ascendex"  => "ascendex"
        "Binance Futures" => "binancefutures"
        "Binance Delivery" => "binancedelivery"
        "Binance" => "binance"
        "Oanda" => "oanda"
        "Kraken" => "kraken"
        "Deribit" => "deribit"
        "Bitfinex" => "bitfinex"
        "Poloniex" => "poloniex"
        "Bybit" => "bybit"
        "Okcoin" => "okcoin"
        "Kucoin" => "kucoin"
        "FTX" => "ftx"
        "Bitmex" => "bitmex"
        "Alpaca" => "alpaca"
        "Gemini" => "gemini"
        => i_broker_name

enable_trades = i_enable_trades ? "" : " d=1"
string delay_qty = use_delay ? " delay=" + str.tostring(i_delay_qty) : ""

i_alert_txt_entry_long = "a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + enable_trades + " b=short c=position t=market" + 
 "\n a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=long q=" + str.tostring(quantity, "#") + " t=market" + enable_trades + delay_qty
 
i_alert_txt_entry_short = "a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + enable_trades + " b=long c=position t=market" + 
 "\n a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=short q=" + str.tostring(quantity, "#") + " t=market" + enable_trades + delay_qty

var string temp_txt_SL_long = ""
var string temp_txt_SL_short = ""

var string temp_txt_TP_long = ""
var string temp_txt_TP_short = ""

if use_sl == "Percent"

    temp_txt_SL_long  := "sl=-" + str.tostring(sl_input_perc * 100) + "%"
    temp_txt_SL_short := "sl=" + str.tostring(sl_input_perc * 100) + "%"

else if use_sl == "Price"

    temp_txt_SL_long  := "fsl=" + str.tostring(final_SL_Long)
    temp_txt_SL_short := "fsl=" + str.tostring(final_SL_Short)

if use_tp == "Percent"

    temp_txt_TP_long := "p=" + str.tostring(tp_input_perc * 100) + "%" 
    temp_txt_TP_short := "p=-" + str.tostring(tp_input_perc * 100) + "%" 

else if use_tp == "Price"

    temp_txt_TP_long  := "fpx=" + str.tostring(final_TP_Long)
    temp_txt_TP_short := "fpx=" + str.tostring(final_TP_Short)  

i_alert_txt_exit_SL_long  = "a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=long c=position t=market " + temp_txt_SL_long + enable_trades 
i_alert_txt_exit_SL_short = "a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=short c=position t=market " + temp_txt_SL_short + enable_trades 
i_alert_txt_exit_TP_long  = "a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=long c=position t=market " + temp_txt_TP_long + enable_trades 
i_alert_txt_exit_TP_short = "a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=short c=position t=market " + temp_txt_TP_short + enable_trades 

string final_alert_txt_entry_long = i_alert_txt_entry_long
string final_alert_txt_entry_short = i_alert_txt_entry_short

if i_use_borrow_repay and i_broker_name == "Binance"

    final_alert_txt_entry_long := "a=" + i_account_name + " e=" + broker_mode + "y=borrow w=" + i_asset_borrow_repay + " q=" + str.tostring(i_qty_borrow_repay, "#") + enable_trades +
     "\n a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + enable_trades + " b=short c=position t=market" + delay_qty +
     "\n a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=long q=" + str.tostring(quantity, "#") + " t=market" + enable_trades + delay_qty +
     "\n a=" + i_account_name + " e=" + broker_mode + "y=repay w=" + i_asset_borrow_repay + " q=" + str.tostring(i_qty_borrow_repay, "#") + enable_trades

    final_alert_txt_entry_short := "a=" + i_account_name + " e=" + broker_mode + "y=borrow w=" + i_asset_borrow_repay + " q=" + str.tostring(i_qty_borrow_repay, "#") + enable_trades +
     "\n a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + enable_trades + " b=long c=position t=market" + delay_qty +
     "\n a=" + i_account_name + " e=" + broker_mode + " s=" + product_type_ticker + " b=short q=" + str.tostring(quantity, "#") + " t=market" + enable_trades + delay_qty +
     "\n a=" + i_account_name + " e=" + broker_mode + "y=repay w=" + i_asset_borrow_repay + " q=" + str.tostring(i_qty_borrow_repay, "#") + enable_trades

//i_alert_txt_entry_long  := final_alert_txt_entry_long
//i_alert_txt_entry_short := final_alert_txt_entry_short

if show_alerts_debug and barstate.islastconfirmedhistory

    var label lblTest = na

    label.delete(lblTest)

    string label_txt = i_alert_txt_entry_long

    if use_sl != "None"
        label_txt := label_txt + "\n" + i_alert_txt_exit_SL_long

    if use_tp != "None"
        label_txt := label_txt + "\n" + i_alert_txt_exit_TP_long

    t = time + (time - time[1]) * 25

    lblTest := label.new(
     x            = t,
     y            = ta.highest(50),
     text         = label_txt,
     xloc         = xloc.bar_time,
     yloc         = yloc.price,
     color        = color.new(color = color.gray, transp = 0),
     style        = label.style_label_left,
     textcolor    = color.new(color = color.white, transp = 0),
     size         =  size.large
     )

// # ========================================================================= #
// #                   |   Strategy Calls and Alerts |
// # ========================================================================= #

if bull and TradeDateIsAllowed() 

    strategy.entry(id = "Long", direction =  strategy.long, comment = "Long", alert_message = i_alert_txt_entry_long, qty = nb_contracts)
    alert(i_alert_txt_entry_long, alert.freq_once_per_bar)
    
else if bear and TradeDateIsAllowed()
    strategy.entry(id = "Short", direction =  strategy.short, comment = "Short", alert_message = i_alert_txt_entry_short, qty = nb_contracts)
    alert(i_alert_txt_entry_short, alert.freq_once_per_bar)

//quantity := quantity * 2

strategy.exit(id = "Exit Long",  from_entry = "Long",  stop = (use_sl != "None") ? final_SL_Long : na,  comment_loss = "Long Exit SL", alert_loss  = (use_sl != "None") ? i_alert_txt_exit_SL_long : na,   limit = (use_tp != "None") ? final_TP_Long  : na, comment_profit = "Long Exit TP", alert_profit = (use_tp != "None") ? i_alert_txt_exit_TP_long : na)   
strategy.exit(id = "Exit Short", from_entry = "Short", stop = (use_sl != "None") ? final_SL_Short : na, comment_loss = "Short Exit SL", alert_loss = (use_sl != "None") ? i_alert_txt_exit_SL_short : na, limit = (use_tp != "None") ? final_TP_Short : na, comment_profit = "Short Exit TP", alert_profit = (use_tp != "None") ? i_alert_txt_exit_TP_short : na)   

if strategy.position_size > 0 and low < final_SL_Long and use_sl != "None"
    alert(i_alert_txt_exit_SL_long, alert.freq_once_per_bar)

else if strategy.position_size < 0 and high > final_SL_Short and use_sl != "None"
    alert(i_alert_txt_exit_SL_short, alert.freq_once_per_bar)

if strategy.position_size > 0 and high > final_TP_Long and use_tp != "None"
    alert(i_alert_txt_exit_TP_long, alert.freq_once_per_bar)

else if strategy.position_size < 0 and low < final_TP_Short and use_tp != "None"
    alert(i_alert_txt_exit_TP_short, alert.freq_once_per_bar)

// # ========================================================================= #
// #                   |   Reset Variables |
// # ========================================================================= #