Ocean Theory Grid Trading Strategy
This strategy utilizes the grid trading method in ocean theory to place buy and sell orders within a preset price range. The strategy features automatic calculation of grid price range and uniform distribution of…
Overview
This strategy utilizes the grid trading method in ocean theory to place buy and sell orders within a preset price range. The strategy features automatic calculation of grid price range and uniform distribution of grid lines, which helps effectively manage risks.
Strategy Logic
The strategy first calculates the upper and lower bounds of the price grid based on user's choice or default settings. There are two ways of calculation: getting the highest and lowest prices in the backtesting period, or computing moving averages over a timeframe. Then grid lines are uniformly distributed according to the number of grids set by user.
The trading signals are generated based on the relationship between price and grid lines. When the price is below a grid line, a long position is opened at the grid line price with fixed quantity; when the price goes above a grid line, the position is closed at the grid line below. As price fluctuates within the grid, the positions change accordingly to gain profit.
Specifically, the strategy maintains a grid line price array and a bool array indicating whether orders are placed at each line. When price is below a line with no orders, long position is opened at the line; when price is above a line while orders exist at the line below, positions are closed at the lower line. Grid trading is implemented this way.
Advantages
Grid range is calculated automatically, avoiding manual setting difficulty. Different calculation options are available.
Grid lines are distributed evenly to avoid overtrading due to dense grids. Number of grids can be adjusted.
Grid trading method effectively controls risks. Profit can be gained as long as price fluctuates within the grid.
No price direction assumption, suitable for range-bound market.
Customizable commission and position size settings for different trading instruments.
Visualization of grid lines helps understand trading situation.
Risks
Price breakout risks. Breaking the upper or lower grid limits can lead to greater losses.
Excessive grid space risks. Grids too loose cannot profit easily while too narrow increases costs. Balance is needed.
Prolonged holding risks. Long holding makes profit difficult yet increases costs.
Improper parameter setting risks. Backtesting period or moving average period can affect grid range calculation if set inappropriately.
Systemic market risks. More suitable for range-bound instead of long-term trended markets.
Enhancement
Optimize grid parameters. Comprehensively consider market conditions, costs etc. to optimize number of grids, lookback period etc.
Introduce dynamic grid range adjustment. Adapt grid ranges when significant market change occurs.
Incorporate stop loss mechanisms. Set proper stop loss lines to limit losses. Can be adjusted dynamically.
Add filters using other indicators. Such as Bollinger Bands, trend indicators etc. to avoid improper trading.
Improve capital usage efficiency. Introduce volatility analysis to reduce trading during steady periods.
Conclusion
The strategy realizes risk-controllable range trading by leveraging grid trading principles. The automatic grid calculation and uniform distribution offer advantages that suit various markets through parameter tuning. Risks are limited and easy to operate. However, limitations exist and continuous improvements are needed to adapt to evolving markets. Overall, the strategy provides a standardized and parametric approach to implementing grid trading.
Parameters
| Name | Default | What it controls |
|---|---|---|
| v_input_1 | true | (?Grid Bounds)Use Auto Bounds? |
| v_input_2 | 0 | (Auto) Bound Source: Hi & Low | Average |
| v_input_3 | 250 | (Auto) Bound Lookback |
| v_input_4 | 0.1 | (Auto) Bound Deviation |
| v_input_5 | 0.285 | (Manual) Upper Boundry |
| v_input_6 | 0.225 | (Manual) Lower Boundry |
| v_input_7 | 8 | (?Grid Lines)Grid Line Quantity |
Source Pine Script
/*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)
Published by ChaoZhang on the FMZ strategy square · last modified 2023-10-13. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.
Build this with AgenKit
A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.
/agenkit build a grid bot with inventory caps and order deduplication from strategies/Ocean-Theory-Grid-Trading-Strategy.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- Get tests, backtest, risk controls and a paper-trading switch
Understand it first
Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.
Related specs
- Adaptive Bollinger Bands Grid Trading Strategy with Dynamic Level AdjustmentPine Script · Grid · 1d
- Adaptive Grid Trading Strategy Based on Quantitative Trading PlatformPine Script · Grid · 1h
- Assassins Grid B A Dynamic Grid Trading StrategyPine Script · Grid · 1d
- Bollinger Fibonacci Grid Tracking Trend StrategyPine Script · Grid · 1h
- Grid Trading Risk Hedging StrategyPine Script · Grid · 5m
- Multi Zone MA100 Price Retracement Smart Grid Trading StrategyPine Script · Grid · 1d