风险告知书,代码开源,使用风险自担,和作者无关,代码只用于学习研究使用,不做交易参考,全部内容作者业余时间研究,只做策略思路,技术分享,不做交易参考建议
在网格的配置中,我保留了参数可以单独开启买入,卖出网格,也可以买卖网格一起开启形成循环的买卖做T网格,我这里采用单独开启买入网格,我一般不用网页做买入,我一般是检测持股卖出

一、策略定义与核心理念
网格卖出策略是一种基于价格波动的自动分批止盈方法,其核心思想是:当股价相对于某个基准价上涨达到预设幅度时,自动卖出固定数量(或固定金额、固定比例)的持仓,锁定利润,并将该次卖出价格作为新的基准价,形成动态上移的卖出网格。该策略通常与网格买入策略配合,构成完整的网格交易系统,通过捕捉市场价格的上下波动,反复赚取差价
下面是我绘制的大概原理情况,网格多数用来做检测持股卖出

二、策略的核心逻辑与关键要素
1. 基准价的动态设定
-
初始基准价:若无历史交易记录,通常取昨日收盘价或开盘参考价(由get_base_price函数获取)。
-
运行期基准价:取该股票最后一次交易(买入或卖出)的成交价格,从交易日志中读取。这使得基准价始终跟随最新成交价,确保网格的连续性。
-
基准价的作用:作为计算涨幅的参照点,决定了卖出触发的位置。
2. 触发条件
-
监控对象:实时行情最新价(last_price)。
-
涨幅计算:涨幅 = (最新价 – 基准价) / 基准价 × 100%。
-
触发阈值:当涨幅 ≥ 预设的“上涨比例”(如1%)时,触发卖出。该阈值决定了网格的密度——阈值越小,网格越密,交易越频繁。
3. 卖出数量确定
根据交易模式(trader_type)计算应卖数量,但不得超过当前可用持仓:
-
数量模式:每次固定卖出指定股数(如100股)。
-
金额模式:每次卖出指定金额的股票,按最新价折算股数(amount = 金额 / 价格),并经过adjust_amount调整至符合最小交易单位(如100股的整数倍)。
-
百分比模式:按账户总资产的一定比例卖出,amount = 总资产 × 百分比 / 价格,同样调整至合规股数。
4. 执行与记录
-
满足触发条件且可用持仓足够(≥10股)时,通过passorder发出卖出委托。
-
记录本次交易信息(股票代码、名称、类型、价格、时间等)到日志文件,供后续基准价更新使用。
-
为防止首次运行时误记录历史数据,代码中通过标志a.gd_sell控制第一次循环不写入日志。
5. 基准价更新机制
卖出成功后,最新成交价成为新的基准价,下一次上涨需基于新基准价重新计算涨幅。这形成了“卖出→基准价上移→再上涨再卖出”的阶梯式止盈路径。

网格卖出策略的本质是将价格波动转化为可控的收益流。它通过动态基准价和固定涨幅阈值,构建了一个“上涨即卖出”的自动止盈系统。其核心思路可概括为:
-
分散风险:分批卖出,避免一次性决策失误。
-
顺应波动:利用市场固有的上下波动赚取差价,而非预测方向。
-
机械执行:完全自动化,排除情绪干扰,确保交易纪律。
-
循环反馈:每次交易后更新基准价,使网格自适应市场,形成正反馈循环。
该策略是量化交易中经典的网格交易法的组成部分,适合风险偏好适中、追求稳定收益的投资者,尤其适用于震荡市中的指数基金或高流动性个股。通过合理设置参数并与网格买入策略协同,可在控制风险的前提下,长期从市场波动中获利。
下面是策略框架运行的流程图方便理解


源代码方便大家去理解策略思路
def run_gd_trade_sell(c):
'''
网格卖出
"网格卖出设置":"网格卖出设置*********",
"是否开启网格卖出":"是",
"上涨比例":1,
'''
path=c.text['记录文件路径']
up_ratio=c.text['上涨比例']
trader_type=c.text['交易模式']
value=c.text['下单值']
position=get_position(c,c.account,c.account_type)
account=get_account(c,c.account,c.account_type)
if position.shape[0]>0:
position=position[position['持仓量']>=10]
if position.shape[0]>0:
hold_list=position['证券代码'].tolist()
av_amount_dict=dict(zip(position['证券代码'],position['可用数量']))
else:
hold_list=[]
av_amount_dict={}
else:
hold_list=[]
av_amount_dict={}
if check_is_trader_date_1(c):
df=get_trader_stock(c)
if df.shape[0]>0:
for stock,name in zip(df['证券代码'],df['名称']):
try:
print('***************************网格卖出{} {}************************************************************************************'.format(stock,name))
now_date=int(''.join(str(datetime.now())[:10].split('-')))
date_time=int(''.join(str(datetime.now()).split('.')[0][-8:].split(':')))
log=check_trader_log(c)
price=get_price(c,stock)
price=round(price,3)
if log.shape[0]>0:
log=log[['证券代码','名称',"类型",'交易模式',
'交易方向','交易值','交易价格','交易时间','交易日']]
log=log.sort_values(by='交易时间',ascending=True)
log['交易日']=log['交易日'].astype(int)
log=log[log['交易日']==now_date]
else:
log=pd.DataFrame()
#获取开始的基础价格
if log.shape[0]>0:
log_stock=log[log['证券代码']==stock]
if log_stock.shape[0]>0:
base_price=log_stock['交易价格'].tolist()[-1]
last_time=log_stock['交易时间'].tolist()[-1]
stats=True
else:
base_price=get_base_price(c,stock)
last_time=93000
stats=False
else:
base_price=get_base_price(c,stock)
last_time=93000
stats=False
if stats==True:
tick=get_stock_lx_tick(c,stock,date=str(now_date))
tick=tick[tick['time']>=last_time]
else:
tick=get_stock_lx_tick(c,stock,date=str(now_date))
if tick.shape[0]>0:
lastClose_list=tick['lastPrice'].tolist()
#最新值
last_price=lastClose_list[-1]
#目前的涨跌幅
last_zdf=((last_price-base_price)/base_price)*100
last_zdf=round(last_zdf,3)
#涨幅大于目前涨跌幅
if last_zdf>=up_ratio:
print('触发网格卖出{} 最新价{},基准价{},涨跌幅{}大于目标涨跌幅{}'.format(stock,last_price,base_price,last_zdf,up_ratio))
if trader_type=='数量':
amount=value
elif trader_type=='金额':
amount=value/price
amount=adjust_amount(stock,amount)
elif trader_type=='百分比':
total=account['总资产']
value=total*value
amount=value/price
amount=adjust_amount(stock,amount)
else:
amount=0
av_amount=av_amount_dict.get(stock,0)
if av_amount>=amount:
amount=amount
else:
amount=av_amount
if check_is_sell(c,c.account,c.account_type,stock=stock,amount=amount) and amount>=10:
maker='{},网格卖出,{},{},{},{}'.format(c.st_name,stock,'sell',amount,price)
passorder(c.sell_code, 1101,c.account, stock, c.sell_price_code, 0, amount, maker,1,maker,c)
trader_log=pd.DataFrame()
trader_log['证券代码']=[stock]
trader_log['名称']=[name]
trader_log['类型']=['网格卖出']
trader_log['交易模式']=[trader_type]
trader_log['交易方向']=['sell']
trader_log['交易值']=[value]
trader_log['交易价格']=[price]
trader_log['交易时间']=[int(date_time)]
trader_log['交易日']=[int(now_date)]
#第一次循环运行卖出不记录
if a.gd_sell==0:
print(stock,'第一次循环运行卖出不记录********')
a.gd_sell=1
else:
log=pd.concat([log,trader_log],ignore_index=True)
if log.shape[0]>0:
log['证券代码']=log['证券代码'].apply(lambda x: '0'*(6-len(str(x)))+str(x))
else:
log=log
log.to_excel(r'{}'.format(path))
print(maker)
else:
print(stock,'卖出失败可能没有持股')
else:
print('没有触发网格卖出{} 最新价{},基准价{},涨跌幅{}小于目标涨跌幅{}'.format(stock,last_price,base_price,last_zdf,up_ratio))
else:
print(str(datetime.now())[:-7],stock,'网格卖出没有数据/拐点触发交易时间大于15:00')
except Exception as e:
print(e,stock,'网格卖出有问题*******************')
else:
print('网格卖出没有自定义交易股票池*********')
else:
print('{}网格卖出目前不是交易时间*********'.format(datetime.now()))

