이 전략은 해양 이론의 격자 거래 방법을 적용하여 설정된 가격 범위 내에서 균등하게 분산된 격자 라인을 사용하여 가격과 격자 라인과의 관계에 따라 구매 및 판매 작업을 수행한다. 이 전략은 자동으로 격자 가격 범위를 계산하고 균등하게 분산된 격자 라인 등의 특징을 가지고 있어 위험을 효과적으로 제어할 수 있다.
이 전략은 우선 사용자 선택 또는 기본 설정에 따라 가격 격자의 상하를 계산한다. 그 격자의 최고 가격과 최저 가격이다. 계산 방법은 두 가지로, 하나는 재측정 주기 내의 최고 가격과 최저 가격을 찾는 것, 두 번째는 일정 주기 동안의 평균선을 계산하는 것이다.
거래 신호의 발생은 가격과 격자선과의 관계에 의존한다. 가격이 아래의 격자선보다 낮을 때, 그 격자선에서 일정한 수량으로 더 많은 입장을 취한다. 가격이 위의 격자선보다 높을 때, 그 격자선에서 일정한 수량으로 더 적은 입장을 취한다. 이렇게 가격의 변동과 함께, 입장은 또한 격자 내에서 변동하여 이익을 얻는다.
구체적으로, 전략은 각 격자 라인마다 상권이 있는지 여부를 나타내는 격자 라인 가격 배열과 bool 배열을 유지한다. 어떤 격자 라인보다 가격이 낮고 그 라인에는 상권이 없는 경우, 그 라인에서 더 많은 가격을 매긴다. 어떤 격자 라인보다 가격이 높고 그 아래에 있는 격자 라인에는 상권이 있는 경우, 그 아래에 있는 격자 라인에서 평점을 한다.
그리드 구간을 자동으로 계산하여 수동 설정의 어려움을 피할 수 있습니다. 다른 계산 방법을 선택할 수 있습니다.
균일하게 배포된 그리드 라인, 그리드 밀도가 과도한 거래로 이어지는 것을 방지한다. 그리드 라인의 수는 조정할 수 있다.
격자 거래 방식을 사용하면 위험을 효과적으로 제어 할 수 있으며 격자 내에서 가격 변동은 항상 수익을 얻을 수 있습니다.
가격에 대한 방향성이 예상되지 않고, 충격적인 상황에 적용된다.
수요율과 포지션 수를 사용자 정의 할 수 있으며, 다양한 거래 유형에 적합합니다.
그레드 라인을 시각적으로 보여 주고 거래 상황을 파악할 수 있다.
그리드 상부 하위 경계를 넘으면 손실이 커질 수 있다.
그리드 간격이 너무 넓으면 수익이 떨어지지만 그리드 간격이 너무 좁으면 수수료가 증가합니다. 균형이 필요합니다.
지분 기간이 너무 길다는 위험. 지분 기간이 너무 길다는 것은 수익을 내기 어렵고, 수수료 손실을 증가시킬 수 있다.
매개 변수 설정이 잘못되면 위험하다. 회수주기나 평균선주기 같은 매개 변수 설정이 잘못되면 격자 간격 계산에 영향을 줄 수 있다.
시장의 체계적 위험. 이 전략은 장기적인 일방적인 행위에 적합하지 않고, 충격적인 행위에 더 적합하다.
최적화 그리드 파라미터 설정 ᆞ 종합적으로 시장 특성, 거래 비용 등의 요인을 고려하고, 최적화 그리드 수, 재검사 주기 등의 파라미터 ᆞ
격자 구간 동적 조정. 시장이 큰 변화가 있을 때 격자 구간 동적 조정 메커니즘을 도입할 수 있다.
스포드 메커니즘에 가입하십시오. 합리적인 스포드 라인을 설정하여 과도한 손실을 피하십시오. 스포드 라인은 또한 동적으로 조정할 수 있습니다.
부린라인, 트렌드 지표 등과 같은 다른 지표와 함께 거래를 필터링하십시오. 부적절한 거래를 피하십시오.
자본 사용 효율을 최적화한다. 냉열 분석을 추가하고, 변동이 적을 때 거래를 줄인다.
이 전략은 격자 거래 원리를 활용하여 위험을 제어할 수 있는 격자 거래를 구현한다. 이 전략은 자동 계산 격자, 균등 분배 격자 등의 장점을 가지고 있으며, 매개 변수를 조정하여 서로 다른 시장 환경에 적응할 수 있다. 위험은 제어할 수 있고 작동하기 쉽다. 그러나 전략에는 시장 변화에 적응하기 위해 지속적인 최적화가 필요한 한계가 있다. 전반적으로 이 전략은 격자 거래에 대해 표준화되고 변수화 가능한 구현 방법을 제공한다.
/*backtest
start: 2023-09-12 00:00:00
end: 2023-10-12 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
strategy.initial_capital = 50000
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
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)