장기 단기 적응적 동적 그리드 전략

저자:차오장날짜: 2024-03-19 14:19:12
태그:

img

전반적인 설명

이 전략은 파인 스크립트를 기반으로 한 긴 짧은 적응적 동적 그리드 거래 전략이다. 이 전략의 핵심 아이디어는 최근 가격 최고와 최저 또는 간단한 이동 평균을 기반으로 그리드의 상부 및 하부 경계를 자동으로 계산하고, 그 다음이 범위를 여러 그리드 라인으로 균등하게 나누는 것입니다. 가격이 특정 그리드 라인에 도달하면 그 수준에서 긴 포지션을 열거나 포지션을 닫을 것입니다. 이러한 방식으로 전략은 가격 스프레드를 포착하기 위해 범위 시장에서 지속적으로 포지션을 열고 닫을 수 있습니다. 동시에, 그리드 경계를 동적으로 조정함으로써 다른 시장 트렌드에 적응 할 수 있습니다.

전략 원칙

  1. 그리드 경계를 계산합니다. 사용자의 선택에 따라 경계는 최근 N 촛불의 가장 높고 가장 낮은 지점에서 계산할 수 있으며, 범위를 비율로 넓히거나 좁힐 수 있습니다. 또는 최근 N 촛불의 폐쇄 가격의 간단한 이동 평균에 기초하여 상향 및 하향 오차 비율을 설정할 수 있습니다.

  2. 그리드 라인 배열을 생성합니다. 그리드 라인의 정해진 수에 따라 그리드 라인 가격 배열을 생성하기 위해 그리드 범위를 균등하게 나누십시오.

  3. 엔트리 / 추가 위치. 그리드 라인을 아래에서 위로 가로질러. 현재 종료 가격이 그리드 라인 가격보다 작고 그 그리드 라인 상에 위치가 없다면 그 수준에서 긴 위치를 열십시오. 이렇게하면 가격이 더 높은 그리드 라인에 도달하면 계속 위치를 추가합니다.

  4. 출구/감소 위치. 위에서 아래로 그리드 라인을 가로지르십시오. 현재 종료 가격이 그리드 라인 가격보다 크며 아래의 그리드 라인 상에 위치가 있다면, 아래의 그리드 라인 상에 긴 위치를 닫습니다. 이렇게하면 가격이 다시 떨어지면 계속 위치를 감소시킵니다.

  5. 동적 조정. 동적 그리드 함수가 선택되면, 그리드의 상부와 하부 경계와 그리드 라인 배열은 각 촛불에 재 계산됩니다. 그래서 그리드는 시장 변화에 따라 지속적으로 적응 할 수 있습니다.

이점 분석

  1. 강한 적응력. 그리드 거래 전략은 범위 및 트렌딩 시장에 모두 적응 할 수 있습니다. 범위 시장에서 그리드 전략은 지속적으로 열고 가격을 늘리기 위해 포지션을 닫을 수 있습니다. 트렌딩 시장에서 그리드가 가격 움직임을 따라가기 때문에 트렌드 이득을 얻기 위해 특정 위치를 유지할 수 있습니다.

  2. 제어 가능한 위험. 각 오픈의 포지션 크기는 설정된 그리드 수에 의해 결정되므로 단일 위험 노출은 작고 제어 할 수 있습니다. 동시에 상위 그리드 라인에 도달하면 수익을 위해 포지션을 닫을 수 있으므로 잠재적 인 손실을 어느 정도 보호합니다.

  3. 높은 수준의 자동화. 이 전략은 기본적으로 수동 개입없이 완전히 자동으로 실행 될 수 있습니다. 장기적인 안정적인 수익을 필요로하는 투자자에게 적합합니다.

  4. 유연한 매개 변수: 사용자는 전략 성능을 최적화하기 위해 시장 특성에 따라 그리드 라인, 동적 그리드 매개 변수 등을 유연하게 설정할 수 있습니다.

위험 분석

  1. 블랙 스완 위험. 극심한 시장 붕괴의 경우 가격이 가장 낮은 그리드 라인 아래로 직접 격차되면 전략은 완전히 위치하고 더 큰 인하에 직면 할 것입니다. 이 위험을 줄이기 위해 손실이 한계에 도달하면 모든 포지션을 닫는 스톱 로스 조건을 설정할 수 있습니다.

  2. 그리드 매개 변수 설정이 잘못되었다. 그리드 밀도가 너무 높으면 열기와 닫기의 스프레드는 매우 작고 거래 비용은 이윤의 대부분을 침식 할 수 있습니다. 그리드 너비가 너무 크면 일회 오픈 비율이 높고 위험 노출이 크습니다. 기본 자산의 특성은 적절한 그리드 매개 변수를 선택하기 위해 신중하게 평가해야합니다.

  3. 기본 위험. 이 전략은 현재 가격에 기초하여 개장 및 폐쇄 조건을 설정합니다. 선물과 같은 시장에서 계약 가격이 기본 가격과 크게 다르면 실제 개장 및 폐쇄 가격은 예상에서 크게 벗어날 수 있습니다.

최적화 방향

  1. 트렌드 필터를 추가한다. 그리드 전략은 일방적인 트렌딩 시장에서 좋은 성능을 발휘하지 않는다. 트렌드 지표는 ADX가 한 임계 이하일 때 그리드를 활성화하고, 트렌드가 명백할 때 그리드를 닫는 것과 같은 필터로 추가될 수 있다.

  2. 신호 최적화. 그리드 + 이동 평균과 같은 다른 신호가 그리드 기반에 겹쳐질 수 있습니다. 즉, 오픈 및 종료는 주로 그리드에 의해 결정되지만 가격이 특정 이동 평균을 넘을 때만 포지션을 열고 그렇지 않으면 포지션을 열지 않습니다. 이것은 빈번한 오픈 및 종료 비용을 줄일 수 있습니다.

  3. 포지션 관리. 현재 전략의 각 그리드의 위치가 고정되어 있습니다. 가격이 시장 평균 가격에서 멀리 떨어져있을 때 각 그리드의 위치를 적절히 줄이고 자본 활용의 효율성을 향상시키기 위해 시장 평균 가격에 가까워지면 위치를 증가시킬 수 있습니다.

  4. 적응력있는 그리드 밀도. 가격 변동성에 따라 그리드 밀도를 동적으로 조정합니다. 변동성이 높을 때 그리드 수를 적절히 증가시킬 수 있습니다. 변동성이 낮을 때 그리드 수를 줄일 수 있습니다. 이것은 그리드 폭을 최적화하고 자본 활용도를 향상시킬 수 있습니다.

요약

적응적 동적 그리드를 통해, 이 전략은 종종 범주 시장에서 가격 스프레드를 벌기 위해 포지션을 열고 닫을 수 있으며, 또한 트렌드 이윤을 얻기 위해 트렌드 시장에서 특정 수준의 노출 방향을 유지할 수 있습니다. 그것은 강한 적응력을 갖춘 중장기량 전략입니다. 그리드 트리거 로직과 포지션 관리를 합리적으로 설정함으로써 안정적인 수익을 얻을 수 있습니다. 그러나, 적절한 스톱 로스 조건을 설정하여 통제해야하는 극단적인 시장 조건과 가격 격차의 위험에주의를 기울여야합니다. 또한, 매개 변수 설정 및 위험 관리에서 최적화를 위한 추가 공간이 있습니다. 트렌드 필터링, 시그널 중복, 포지션 관리, 적응적 그리드 밀도 및 기타 방법을 도입함으로써 전략의 견고성과 수익성을 향상시킬 수 있습니다. 요약하자면, 그리드의 기본 로직에 기반하여, 이 전략은 적응적 메커니즘을 통합하여 투자자에게 새로운 중장기적 아이디어와 양적 참조를 제공할 수 있습니다.


// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © jcloyd

//@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)

더 많은