동적 그리드 트렌드를 따르는 양적 거래 전략

저자:차오장, 날짜: 2024-03-22 16:03:09
태그:

img

전반적인 설명

이 전략의 주요 아이디어는 미리 설정된 가격 범위 내에서 여러 개의 그리드 라인을 분할하고 가격이 그리드 라인에 도달하면 자동으로 포지션을 열고 판매 할 때 포지션을 닫아 변동하는 시장에서 이익을 얻는 것입니다. 동시에이 전략은 최근 가격 추세에 따라 그리드 레이아웃을 적응적으로 최적화 할 수있는 그리드 라인의 위치를 동적으로 조정하는 기능도 있습니다.

전략 원칙

이 전략의 핵심 원칙은 다음과 같습니다.

  1. 먼저, 사용자 설정에 따라 그리드의 상부와 하부 경계 및 그리드 라인의 수를 결정합니다. 경계값은 고정 값이거나 최근 최고와 최저 또는 이동 평균에 따라 자동으로 계산 될 수 있습니다.

  2. 정해진 경계 내에서 가격 범위를 여러 그리드로 나누십시오. 각 그리드 라인은 구매 또는 판매 가격에 대응합니다.

  3. 가격이 각 그리드 라인에 도달하면, 전략은 그 그리드 라인에 해당하는 포지션이 이미 보유되었는지 확인합니다. 그렇지 않으면 포지션을 열고 구매하고, 그렇다면 포지션을 닫고 판매합니다.

  4. 상대적으로 높은 위치에서 판매하고 낮은 위치에서 구매함으로써 전략은 가격이 변동할 때 지속적으로 이익을 얻을 수 있습니다.

  5. 동시에, 사용자가 자동 경계 조정 기능을 활성화하면, 그리드 라인의 위치는 최근 가격 최고와 최저 또는 설정 이동 평균에 따라 적응적으로 조정되어 그리드 레이아웃을 최적화합니다.

위의 원칙을 통해 이 전략은 변동적인 가격 추세에서 자동으로 낮은 구매와 높은 판매를 실현하고, 추세에 따라 수익점을 조정하여 전반적인 수익을 향상시킬 수 있습니다.

이점 분석

이 동적 네트워크 전략은 다음과 같은 장점을 가지고 있습니다.

  1. 강한 적응력. 매개 변수 설정을 통해 다른 시장과 품종에 적응 할 수 있으며 변동하는 시장에 좋은 적응력을 가지고 있습니다.

  2. 높은 수준의 자동화. 전략은 엄격한 수학적 논리와 명확한 포지션 개점 및 폐쇄 지점을 기반으로하므로 완전히 자동화 된 거래를 달성하고 주관적 감정 간섭을 줄일 수 있습니다.

  3. 통제 가능한 위험: 네트워크의 수와 네트워크 경계와 같은 매개 변수를 설정함으로써 각 거래의 위험 노출을 효과적으로 제어할 수 있으며, 이로써 전체 위험은 수용 가능한 범위 내에서 유지될 수 있습니다.

  4. 트렌드 적응성: 트렌드 시장에서 수익성을 향상시키는 가격 추세를 따라 네트워크가 최적화 될 수 있도록 네트워크 경계를 동적으로 조정하는 기능이 전략에 추가됩니다.

  5. 안정적인 승률. 그리드 트레이딩은 기본적으로 가격 변동에 대해 빈번하게 던지고 낮은 수축을 하기 때문에 가격이 변동을 유지하는 한 이 전략은 수익을 계속 얻을 수 있으므로 장기적으로 높은 승률을 가지고 있습니다.

위험 분석

이 전략은 명백한 장점을 가지고 있지만, 또한 특정 위험을 가지고 있습니다.

  1. 트렌드 리스크: 가격이 강한 일방적인 트렌드로 그리드 경계를 넘어서면 이 전략의 수익 공간이 제한되어 큰 리트레이션에 직면 할 수 있습니다.

  2. 매개 변수 최적화의 어려움. 이 전략은 그리드 수, 초기 경계, 동적 경계 매개 변수 등을 포함한 많은 매개 변수를 가지고 있습니다. 다른 매개 변수 조합은 전략 성능에 큰 영향을 미치며 실제 최적화 어려움이 적지 않습니다.

  3. 빈번한 거래: 그리드 전략은 본질적으로 매우 빈번한 포지션 개점 및 폐쇄로 거래 비용이 높고 잠재적인 미끄러짐 위험이 있습니다.

  4. 시장 조건에 대한 강한 의존성. 이 전략은 변동하는 시장에 크게 의존합니다. 가격이 급격한 일방적인 추세로 들어가면 이 전략은 큰 추락에 직면 할 가능성이 있습니다.

이러한 위험을 감안할 때 다음과 같은 측면에서 개선이 가능합니다. 전략 시작을 위한 필터 조건으로 트렌드 판단 지표를 추가하고, 매개 변수 검색 공간과 방법을 최적화하고, 펀드 관리 및 위치 제어 논리를 도입하고, 트렌드 돌파구 폐쇄 논리를 증가시킵니다. 이러한 최적화를 통해 이 전략의 견고성과 수익성을 더욱 향상시킬 수 있습니다.

최적화 방향

위의 분석을 바탕으로 이 전략의 최적화 방향은 주로 다음을 포함합니다.

  1. 트렌드 필터링 조건을 도입하십시오. 트렌드 판단 지표, 이동 평균, ADX 등 전략을 시작하기 전에 트렌드 판단 지표를 추가하십시오. 유동 시장 조건에서 전략을 시작하고 트렌드 시장에서 리트레이싱 위험을 효과적으로 피하기 위해 트렌드 시장을 계속 관찰하십시오.

  2. 매개 변수 검색을 최적화합니다. 유전자 알고리즘, 입자 군집 알고리즘 등과 같은 지능형 알고리즘을 사용하여 최적의 매개 변수 조합을 자동으로 찾고 최적화 효율성과 품질을 향상시킵니다.

  3. 리스크 제어 논리를 강화합니다. 가격 변동성에 따라 그리드 폭을 동적으로 조정하는 것, 폐쇄를 유발하는 최대 리트레이크 문턱을 설정하는 것 등 전략에 더 많은 리스크 제어 논리를 추가하여 리스크를 더 잘 제어하십시오.

  4. 트렌드 스톱 로스를 도입한다. 그리드 경계의 특정 비율과 같은 트렌드 돌파 스톱 로스 라인을 설정한다. 가격이 스톱 로스 라인을 넘어서면 트렌드 시장에서 큰 리트레이스를 피하기 위해 모든 포지션을 닫는다.

  5. 트랜잭션 실행을 최적화합니다. 더 고급한 주문 유형과 주문 알고리즘을 채택하는 것과 같은 트랜잭션 실행 링크를 최적화하여 트랜잭션 빈도와 비용을 최소화하고 실행 효율성을 향상시킵니다.

위의 최적화를 통해 이 전략의 적응력, 견고성 및 수익성이 포괄적으로 향상될 수 있으며 실제 거래 필요에 더 가깝게 될 수 있습니다.

요약

일반적으로 이러한 동적 그리드 트렌드 추후 전략은 그리드 트레이딩의 원리에 기반한 중~고주파량 양적 거래 전략이며, 동적 조정 및 트렌드 적응 메커니즘을 통합합니다. 이 전략의 장점은 강력한 적응력, 높은 자동화 수준, 제어 가능한 위험, 좋은 트렌드 적응력 및 안정적인 승률에 있습니다. 동시에, 트렌드 위험, 매개 변수 최적화의 어려움, 빈도 거래 및 시장 조건에 대한 강한 의존성 등의 위험도 있습니다. 이러한 문제들을 고려하여 트렌드 필터링, 매개 변수 최적화, 위험 강화, 트렌드 스톱 손실 제어, 거래 최적화 및 기타 측면을 개선하여 전략의 전반적인 성능을 향상시킬 수 있습니다.

그리드 트레이딩의 아이디어 자체는 비교적 성숙하고 실용적인 양적 방법이다. 이 전략에 동적 최적화 및 트렌드 적응 메커니즘을 추가함으로써 고전적 그리드 트레이딩의 장점이 확장되고 발전되었다. 이는 투자자들에게 새로운 양적 거래 아이디어와 변동하는 시장에서의 가능성을 제공합니다. 추가 최적화 및 개선으로이 전략은 우수한 중고 주파수 양적 거래 도구가 될 것으로 예상됩니다.


/*backtest
start: 2024-03-01 00:00:00
end: 2024-03-21 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("(IK) Grid Script", overlay=true, pyramiding=14, close_entries_rule="ANY", default_qty_type=strategy.cash, initial_capital=100.0, currency="USD", commission_type=strategy.commission.percent, commission_value=0.1)
i_autoBounds    = input(group="Grid Bounds", title="Use Auto Bounds?", defval=true, type=input.bool)                             // calculate upper and lower bound of the grid automatically? This will theorhetically be less profitable, but will certainly require less attention
i_boundSrc      = input(group="Grid Bounds", title="(Auto) Bound Source", defval="Hi & Low", options=["Hi & Low", "Average"])     // should bounds of the auto grid be calculated from recent High & Low, or from a Simple Moving Average
i_boundLookback = input(group="Grid Bounds", title="(Auto) Bound Lookback", defval=250, type=input.integer, maxval=500, minval=0) // when calculating auto grid bounds, how far back should we look for a High & Low, or what should the length be of our sma
i_boundDev      = input(group="Grid Bounds", title="(Auto) Bound Deviation", defval=0.10, type=input.float, maxval=1, minval=-1)  // if sourcing auto bounds from High & Low, this percentage will (positive) widen or (negative) narrow the bound limits. If sourcing from Average, this is the deviation (up and down) from the sma, and CANNOT be negative.
i_upperBound    = input(group="Grid Bounds", title="(Manual) Upper Boundry", defval=0.285, type=input.float)                      // for manual grid bounds only. The upperbound price of your grid
i_lowerBound    = input(group="Grid Bounds", title="(Manual) Lower Boundry", defval=0.225, type=input.float)                      // for manual grid bounds only. The lowerbound price of your grid.
i_gridQty       = input(group="Grid Lines",  title="Grid Line Quantity", defval=8, maxval=15, minval=3, type=input.integer)       // how many grid lines are in your grid

f_getGridBounds(_bs, _bl, _bd, _up) =>
    if _bs == "Hi & Low"
        _up ? highest(close, _bl) * (1 + _bd) : lowest(close, _bl)  * (1 - _bd)
    else
        avg = sma(close, _bl)
        _up ? avg * (1 + _bd) : avg * (1 - _bd)

f_buildGrid(_lb, _gw, _gq) =>
    gridArr = array.new_float(0)
    for i=0 to _gq-1
        array.push(gridArr, _lb+(_gw*i))
    gridArr

f_getNearGridLines(_gridArr, _price) =>
    arr = array.new_int(3)
    for i = 0 to array.size(_gridArr)-1
        if array.get(_gridArr, i) > _price
            array.set(arr, 0, i == array.size(_gridArr)-1 ? i : i+1)
            array.set(arr, 1, i == 0 ? i : i-1)
            break
    arr

var upperBound      = i_autoBounds ? f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, true) : i_upperBound  // upperbound of our grid
var lowerBound      = i_autoBounds ? f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, false) : i_lowerBound // lowerbound of our grid
var gridWidth       = (upperBound - lowerBound)/(i_gridQty-1)                                                       // space between lines in our grid
var gridLineArr     = f_buildGrid(lowerBound, gridWidth, i_gridQty)                                                 // an array of prices that correspond to our grid lines
var orderArr        = array.new_bool(i_gridQty, false)                                                              // a boolean array that indicates if there is an open order corresponding to each grid line

var closeLineArr    = f_getNearGridLines(gridLineArr, close)                                                        // for plotting purposes - an array of 2 indices that correspond to grid lines near price
var nearTopGridLine = array.get(closeLineArr, 0)                                                                    // for plotting purposes - the index (in our grid line array) of the closest grid line above current price
var nearBotGridLine = array.get(closeLineArr, 1)                                                                    // for plotting purposes - the index (in our grid line array) of the closest grid line below current price
strategy.initial_capital = 50000
for i = 0 to (array.size(gridLineArr) - 1)
    if close < array.get(gridLineArr, i) and not array.get(orderArr, i) and i < (array.size(gridLineArr) - 1)
        buyId = i
        array.set(orderArr, buyId, true)
        strategy.entry(id=tostring(buyId), long=true, qty=(strategy.initial_capital/(i_gridQty-1))/close, comment="#"+tostring(buyId))
    if close > array.get(gridLineArr, i) and i != 0
        if array.get(orderArr, i-1)
            sellId = i-1
            array.set(orderArr, sellId, false)
            strategy.close(id=tostring(sellId), comment="#"+tostring(sellId))

if i_autoBounds
    upperBound  := f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, true)
    lowerBound  := f_getGridBounds(i_boundSrc, i_boundLookback, i_boundDev, false)
    gridWidth   := (upperBound - lowerBound)/(i_gridQty-1)
    gridLineArr := f_buildGrid(lowerBound, gridWidth, i_gridQty)

closeLineArr    := f_getNearGridLines(gridLineArr, close)
nearTopGridLine := array.get(closeLineArr, 0)
nearBotGridLine := array.get(closeLineArr, 1)







더 많은