最近国庆的“大礼”各位小伙伴们都收到了吗?是不是被这波疯牛行情顶得头晕目眩!大宗商品市场一扫前日的低迷不振,扬眉吐气,持续走高。其实,在市场趋势比较明朗的情况下,大家需要做的就是一件简单的事——“低买高卖”。相信这几天大家都恨不得能有三头六臂,频繁在不同品种之间进行操作,抓住每一次低买高卖的机会。那么,有没有一种方法可以解放我们的双手,让我们在市场波动中不用时刻盯盘、手动操作,还能从价格波动中稳健获利呢?这时,自动化的网格交易策略便应运而生,不论是牛市还是熊市,它都能帮助我们实现“低买高卖”的操作逻辑,从而高效应对市场的波动。
网格交易策略是一种在金融市场中应用广泛的技术分析工具,尤其适用于震荡行情或波动性较大的市场。其核心原理是将市场价格划分为多个间隔相等的“网格”,在每个网格节点上自动执行买入或卖出操作,从而在市场价格的上下波动中持续赚取差价。通过这样的方式,网格交易策略不仅省去了我们手动操作的烦恼,还能在自动化执行的同时,更合理地管理资金和仓位,避免因情绪波动或操作失误带来的损失,真正实现稳健盈利。
传统网格策略的优势在于它不需要精确预测市场的走向,而是通过构建买卖价格区间来应对市场波动。虽然网格策略不要求精确预测市场走向,但在一定程度上,它仍然依赖于对市场趋势的理解和判断。策略的设定,如选择牛市或熊市方向,通常基于对市场整体走势的分析。例如,在牛市中,策略可能会更多地关注上涨突破,以便在价格上涨时主动卖出;而在熊市中,策略则可能集中于低位买入,等待反弹。因此,虽然网格策略在操作上是被动的,但其基础设置和方向选择通常是建立在对市场趋势的预测之上的。这种结合使得策略在灵活应对波动的同时,也能更好地适应市场环境。在牛市和熊市中,网格策略的设置和执行会有所不同,策略的方向和交易频率都会根据市场走势进行调整。这种灵活性使得网格策略能够适应各种市场环境,同时通过网格的调整来规避部分风险。
今天我们要介绍的策略是一个基于网格交易原理的自动化策略,专门为牛市和熊市设计。与传统的网格策略不同,我们的策略在价格波动较大、趋势较为明确的情况下更加有效。通过自动捕捉市场中的买卖机会,不仅能在价格区间内进行高效的“低买高卖”,还能够灵活应对市场的趋势变化,从而在牛市和熊市中都能保持稳健的盈利能力。接下来,我们将详细说明这个策略的工作原理和实际操作。
该策略源自优宽量化大神小小梦,经过改编,使其适用于商品期货市场,不废话,直接放代码:
'''backtest
start: 2024-09-19 00:00:00
end: 2024-09-29 00:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
'''
direction = -1 # 网格方向,熊市设置为+1,牛市设置为-1
_GridNum = 10 # 网格节点数量
_GridPointAmount = 1 # 网格节点下单量
_GridPointDis = 4 # 网格节点间距
_GridCovDis = 8 # 网格节点平仓差价
contract = 'FG501' # 合约名称,例如 'TA501C5800'
orderlist = [] # 记录历史订单的列表
_Grid = [] # 网格记录
def trade(dir, amount):
"""
执行交易操作。
:param dir: 交易方向(买入或卖出)
:param amount: 交易数量
"""
exchange.CreateOrder(contract, dir, -1, amount) # 创建订单
Log(exchange.GetTicker(contract).Last) # 记录当前市场价格
Log('当前网格数量:', len(_Grid)) # 记录当前网格数量
def updateorder():
"""
更新当前的历史订单列表。
"""
Sleep(1000 * 5) # 暂停5秒,等待订单信息更新
curorder = exchange.GetHistoryOrders() # 获取历史订单
# 遍历当前订单,如果不在orderlist中则添加
for order in curorder:
if order not in orderlist:
orderlist.append(order)
def UpdateGrid(nowBidsPrice, nowAsksPrice, direction): # 更新网格状态
"""
更新网格状态,根据当前市场价格和方向进行操作。
:param nowBidsPrice: 当前买入价格
:param nowAsksPrice: 当前卖出价格
:param direction: 网格方向(1为上涨,-1为下跌)
"""
# 判断是否需要添加新的网格节点
if len(_Grid) == 0 or (direction == 1 and nowBidsPrice - _Grid[-1]['price'] > _GridPointDis) or \
(direction == -1 and _Grid[-1]['price'] - nowAsksPrice > _GridPointDis):
if len(_Grid) == 0:
Log('策略起始#0000FF') # 策略开始日志
# 确认突破的阶段并记录
if len(_Grid) != 0 and direction == 1 and nowBidsPrice - _Grid[-1]['price'] > _GridPointDis:
Log('第一阶段:向上突破,突破阈值:', nowBidsPrice - _Grid[-1]['price'])
if len(_Grid) != 0 and direction == -1 and _Grid[-1]['price'] - nowAsksPrice > _GridPointDis:
Log('第二阶段:向下突破,突破阈值:', _Grid[-1]['price'] - nowAsksPrice)
# 确定当前交易价格
nowPrice = nowBidsPrice if direction == 1 else nowAsksPrice
# 执行买入或卖出操作
trade('sell', _GridPointAmount) if direction == 1 else trade('buy', _GridPointAmount)
# 更新历史订单
updateorder()
neworder = orderlist[-1] # 获取最新的订单
# 检查新订单状态是否成功
if neworder.Status == 1:
# 添加新的网格节点
_Grid.append({
'price': nowPrice if len(_Grid) == 0 else _Grid[-1]['price'] + _GridPointDis * direction,
'hold': {'price': neworder['AvgPrice'], 'amount': neworder['DealAmount']},
'coverPrice': (nowPrice - direction * _GridCovDis) if len(_Grid) == 0 else _Grid[-1]['price'] + _GridPointDis * direction - direction * _GridCovDis
})
# 检查是否需要平仓
if len(_Grid) > 0 and (
(direction == 1 and nowAsksPrice < _Grid[-1]['coverPrice']) or
(direction == -1 and nowBidsPrice > _Grid[-1]['coverPrice'])):
# 平仓操作
trade('closesell', _Grid[-1]['hold']['amount']) if direction == 1 else trade('closebuy', _Grid[-1]['hold']['amount'])
# 更新历史订单
updateorder()
Log('第二阶段:价格跌破平仓价格盈利平仓,去除最后添加网格' if direction == 1 else '第二阶段:价格突破平仓价格盈利平仓,去除最后添加网格', '#FF0000')
_Grid.pop() # 移除最后一个网格节点
# 检查网格数量是否超过限制
elif len(_Grid) > _GridNum:
# 平仓操作
trade('closesell', _Grid[0]['hold']['amount']) if direction == 1 else trade('closebuy',_Grid[0]['hold']['amount'])
# 更新历史订单
updateorder()
Log('第三阶段:网格数量过多亏损平仓,去除初始网格' if direction == 1 else '第三阶段:网格数量过多亏损平仓,去除初始网格', '#00FF00')
_Grid.pop(0) # 移除第一个网格节点
def main():
global _Grid, orderlist
exchange.SetContractType(contract) # 设置合约类型
while True:
ticker = _C(exchange.GetTicker) # 获取市场数据
UpdateGrid(ticker['Buy'], ticker['Sell'], direction) # 更新网格
msg = ""
# 构建网格状态消息
for grid in _Grid:
msg += str(grid) + "\n"
# 记录当前状态
LogStatus(_D(), _C(exchange.GetAccount), "\n", "_Grid.length:", len(_Grid), "_GridNum:", _GridNum, "\n", msg)
Sleep(500) # 暂停500毫秒
本文中的网格策略包含两个方向设定,分别适用于牛市和熊市:
牛市方向(direction = -1):
在牛市中,市场价格趋势为上涨,因此策略通过在价格上升的过程中分批卖出并在回调时买入,利用价格上涨的过程中建立多单并逐步获利。在代码中,direction = -1
表示牛市策略,交易逻辑是当价格向上突破时(即当前买入价nowBidsPrice
相对上一网格价格上涨超过一定间距_GridPointDis
),策略触发卖出操作。当价格回调并跌破平仓价格时,系统会自动平仓以确保盈利。
熊市方向(direction = 1):
在熊市中,市场价格呈下跌趋势,策略会在价格下跌时分批买入并在反弹时卖出。此时,direction = 1
,意味着熊市策略会在市场价格下跌到设定的网格节点时进行买入操作,而当市场价格反弹至平仓价格时平仓以获取利润。
本策略通过_GridNum
设置网格节点数量,通过_GridPointDis
定义每个网格节点间距,确保交易频率适中,同时避免过于频繁的交易导致高频亏损。在UpdateGrid
函数中,系统根据当前买入价或卖出价动态更新网格节点,网格更新逻辑如下:
coverPrice
),当市场回调时进行自动平仓操作。该策略针对市场回调和过多网格节点设置了两种平仓机制:
coverPrice
),系统会触发自动平仓,将盈利的订单从网格中移除。_GridNum
时,系统会将最早的网格节点进行平仓,避免积累过多持仓造成潜在风险。这两种机制的结合不仅确保了在盈利的情况下及时锁定收益,同时也限制了网格节点的数量,防止由于过多持仓而导致资金压力过大。
相比传统的网格交易策略,本策略在以下几方面进行了优化:
orderlist
追踪每次交易的执行情况,并确保所有订单记录被完整处理。此外,通过设定最大网格节点数量,避免因过多持仓导致策略失效或发生不可预期的风险。2024年,在经济下行预期的期望下,玻璃的价格确实走了一波过山车,在这样的市场环境中,交易策略的灵活性与适应性显得尤为重要。
相信大家最关注的还是该策略的收益状况。首先,我们以最近的牛市为例(2024年9月19日至2024年9月27日),仅仅使用1手合约,就可以实现19015元的收益。在此期间,玻璃期货价格从1004元上升至1257元,单一持仓仅带来了5060元的收益。而通过我们的低买高卖策略,我们进一步利用价格波动,成功实现了更多的利润,充分体现了该策略在实际操作中的有效性和收益潜力。
熊市阶段(2024年5月30日至2024年9月19日),期货价格从1782下降至1004,单一持仓收益为15560,而网格收益为81020,实现6倍收益。
注意:
该策略的不足之处在于假设市场呈现震荡走势,如果趋势判断失误,可能导致频繁止损(可以想象为逆市操作)。此外,不合理的止损位设置也可能导致过早止损,从而错失反弹机会。同时,多个网格头寸在单边市场中可能导致资金被深套,难以平仓。市场波动较大时,滑点和交易成本的增加也会影响盈利,投资者可能因恐慌或贪婪做出非理性决策。
为改善这些问题,可以引入趋势识别指标,以判断市场方向并及时调整网格策略。同时,根据市场波动性合理设定止损,避免过早止损的情况。加强资金管理,设置合理的仓位比例,以防止在单边市场中资金被套牢。此外,控制交易频率,以降低交易成本和滑点影响,最后,投资者应加强心理素质训练,以保持冷静并严格执行策略。
说点人话,其实这种类型的策略具有极强的时效性,大家需要在对市场具有敏锐判断的基础上使用才能获得最大的收益,另外,这种策略也可以适用于期权市场,相信期权市场的波动会令该策略的收益实现“翻三番”的效果,大家有兴趣可以使用模拟盘尝试一下。