자기 적응형 양자 그리드 거래 전략

저자:차오장, 날짜: 2024-02-02 18:08:22
태그:

img

전반적인 설명

이 전략은 변동적인 시장 속에서 안정적인 수익을 달성하기 위해 동적 거래 그리드를 설정합니다. 미리 설정된 그리드 라인의 수에 따라 자동으로 그리드 간격 및 상위/하계도를 계산합니다. 가격이 각 그리드 라인을 통과할 때, 긴/단지 포지션은 팩으로 구축됩니다. 가격이 원래 그리드 라인을 다시 때 수익이 취득됩니다. 전략은 변화하는 시장 조건에 적응하기 위해 그리드 매개 변수의 수동 및 자동 조정 모두를 지원합니다.

전략 논리

  1. 입력 매개 변수를 기반으로 그리드 경계 및 그리드 라인 가격 배열을 계산합니다.

  2. 가격이 해당 명령어 없이 그리드 라인 아래로 떨어지면, 긴 명령어는 그리드 라인 가격에 배치됩니다. 가격이 기존 위치로 이전 그리드 라인 (첫 번째 제외) 이상으로 상승하면, 이전 라인의 긴 명령어는 종료됩니다.

  3. 자동 조정 기능이 활성화되면 최근 촛불 데이터에 기초하여 그리드 상부/하부 제한, 그리드 간격 및 그리드 배열이 주기적으로 재 계산됩니다.

이점 분석

  1. 변동적인 시장 속에서 안정적인 수익을 창출합니다. 전체 수익을 달성하기 위해 다양한 가격 수준에서 롱/쇼트 포지션이 배치되어 폐쇄됩니다.

  2. 수동 및 자동 매개 변수 조절을 지원합니다. 수동 조정은 더 나은 제어 기능을 제공하지만 개입이 필요합니다. 자동 조정은 작업 부하를 줄이고 변화하는 시장 역학에 적응합니다.

  3. 최대 손실은 최대 회선 수를 제한하여 제한됩니다. 가격이 모든 회선선을 깨면 위험이 함축됩니다.

  4. 트레이드 당 이익/손실을 조정하기 위해 그리드 간격을 조정합니다. 더 작은 간격은 트레이드 당 노출을 줄입니다.

위험 분석

  1. 휘프스와에 갇힐 위험이 있습니다. 네트워크 범위 내에서 빈번한 가격 변동이 손실로 이어질 수 있습니다.

  2. 충분한 초기 자본이 필요합니다. 충분한 자금이 부족하면 충분한 네트워크 라인을 지원할 수 없습니다.

  3. 극심한 그리드 숫자는 수익을 저하시킨다. 너무 적은 그리드가 변동성을 최대한 활용하지 못하며 너무 많은 그리드가 거래당 최소한의 수익을 가져옵니다. 최적의 설정을 결정하기 위해 광범위한 테스트가 필요합니다.

  4. 자동 조정 위험 가격 조작 최근 촛불에 의존 하 고 단기 가격 운영에 의해 영향을 받을 수 있습니다.

최적화

  1. 방향별 하향 위험을 더 제한하기 위해 트레일링 스톱 로스 같은 스톱 로스 논리를 도입하십시오.

  2. 기계 학습을 통해 그리드 매개 변수를 최적화합니다. 시장 조건에서 다른 매개 변수를 테스트하고 최적의 적응 매개 변수를 얻기 위해 ML 모델을 훈련하십시오.

  3. 추가적인 기술 지표를 포함합니다. 그리드 양과 매개 변수 조정을 안내하기 위해 MACD 및 RSI와 같은 지표로 현재 트렌드 강도를 평가하십시오.

  4. 최대 허용 당출 비율을 설정하여 위험 통제를 강화합니다. 더 이상의 손실을 방지하기 위해 문턱이 위반되면 전략을 비활성화하십시오.

결론

이 전략은 변동적인 시장의 특성을 완전히 활용하고 파라미터 유연성과 운영 용이성을 제공하는 동적 그리드 거래 프레임워크를 통해 안정적인 이익을 달성합니다. 손실 제어 및 자동 파라미터 최적화에 대한 추가 향상으로 시장 변동으로부터 지속적인 이익을 창출하는 이상적인 모델이 될 수 있습니다.


/*backtest
start: 2024-01-02 00:00:00
end: 2024-02-01 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)



더 많은