止损又叫 “割肉”, 指的是当一个投资组合亏损达到一定比例 及时清仓出局, 以免形成更大的亏损的行为。 止盈是指当盈利大于一定数额, 及时获利了结。
华尔街有一句话: 让损失减少,让利润飞驰。
我们用一组数字来说明止损的重要性, 假设你的资金没有杠杆,从 10w 亏损至 5w ,资金缩水50%。 但是从5w 增长至10w 需要盈利 100% 才行。假设你的资金有1:2 的杠杆,若没有阻止亏损,在亏损达到30%左右,对不起,你爆仓啦。
所以如何卖?在什么时候卖? 是我们必须要深思熟虑的问题。
由于A股市场散户居多, 无论跌涨都会束手无策。经常心里想一套, 手上做一套。 人性的缺点在市场上会被无限放大,这时候就需要程序化交易来弥补人性的缺点。 在百度上随手一搜都能搜出很多止损方案, 但是这些止损方案可不可行?有什么优缺点呢?
在这里提供了几个简单的止损方案的模板, 在写这些代码的时候考虑了 小白用户的体验,用户只需将相应的代码复制粘贴到自己的策略中, 并设置相关参数就能顺利使用。 详细调用方法 请看 源代码 开头部分。
为了获得更好的止损效果, 我建议将调仓频率设置为月调仓。
接下来是各个止损方案的介绍和地址。
时间止损
时间止损认为时间是有价值的,若在一定的时间内某股票的回报收益低于一个预设值就认为该交易低于预期,选择卖出。 这是一个非常简单的止损策略, 由于止损线是固定的, 所以不能很好的减少回撤。若不是专门研究时间止损, 不建议使用。
if 持仓时间> X 天 and 区间涨幅 小于Y% : 卖出止损else:继续持有
详细地址: https://www.ricequant.com/community/topic/1417
限价止损
限价止损 将买入价设置为基准价, 一旦股价上涨大于X% 或下跌大于 Y% 就卖出该股。这是也是一个固定止损/止盈价位的止损方案, 和时间止损存在相同问题:不能有效减少回撤。
if 现价>(1+X%)*买入价:卖出 止盈else if 现价<(1-Y%)*买入价:卖出止损else:继续持有
详细地址: https://www.ricequant.com/community/topic/1419/
跟踪止损
跟踪止损 考虑的是该股的回撤, 若回撤大于某预设值X% 就将其卖出。 此方案的止损价会随着最高价的变化而变化, 在股灾和熔断中有很好的表现。
X=允许最大回撤if 现价<持股周期内最高价*(1-X %):卖出止损else:继续持有
详细地址:https://www.ricequant.com/community/topic/1420
阶梯止损
阶梯止损是一种 动态止损策略。 止损价会根据持股周期内最高价的变化而变化。 和跟踪止损的思路类似, 但是止损价的计算方式略有不同, 股灾期间表现良好。 但不及阶梯止损。
止损价= fx( 买入后最高价, 初始止损价 ,阶梯长度,阶梯变化率)if 现价< 止损价 :卖出止损else:继续持有
详细地址:https://www.ricequant.com/community/topic/1423
时间+ 阶梯 止损
时间+阶梯 止损是将“时间有价值” 和 “动态止损” 这两个思路结合在一起的策略。 止损价会随着 持股周期的变化而变化, 一旦跌破止损价,则卖出。 良好的止损策略。
止损价 =fx ( 持股周期, 期望回报率)if 现价< 止损价:卖出止损
详细地址 :https://www.ricequant.com/community/topic/1424
ATR 止损
ATR止损 会先计算 一个叫做平均真实波幅 (Average True Range )的指标,ATR止损是根据这一指标发散出来编写的策略。
Raw_ATR=max(|今日振幅|, |昨天收盘-今日最高价|,|昨天收盘-今日最低价|)# 未处理ATR = 这三个指标的最大值ATR=moving_average (ATR ,N) #真实ATR 为 Raw_ATR 的N 日简单移动平均,默认N=22
详细地址:https://www.ricequant.com/community/topic/1429
熔断止损
如果大盘跌幅过大, 相当于检测到系统性风险, 于是卖出所有股票,暂停交易出去旅游。
if 今日最低值/ 今日最高值< 0.96: 清仓止损暂停交易20天
【止损】 止损/止盈 方案目录 必读
为了说明止损的重要性, 我特意编写了一个 掷骰子选股法。
随机选 15 只股票 ,平均买入 , 每月调仓。
这是不加任何止损策略的结果, 可见回撤非常大。
大家也可以克隆一下这个策略,试试手气, 看看自己的人品怎么样...
# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import numpy as np import pandas as pd import math import random# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.maxvalue=pd.DataFrame() context.drawdown= 0.08 # 回撤限度 10% #scheduler.run_weekly(buybuybuy,1) scheduler.run_monthly(getstock,1) scheduler.run_monthly(buybuybuy,1) def stoploss(context,bar_dict): pass def createdic(context,bar_dict,stock): if stock not in context.maxvalue.columns: temp=pd.DataFrame({str(stock):[context.portfolio.positions[stock].bought_value]}) context.maxvalue = pd.concat([context.maxvalue, temp], axis=1, join='inner') print(context.maxvalue) def getstock(context,bar_dict): context.stocks=[] fundamental_df = get_fundamentals(query(fundamentals.eod_derivative_indicator.market_cap,)) all_stock=fundamental_df.columns.values #print(str(all_stock)) for x in range(15): code=random.randint(0,len(all_stock)-1) stock=all_stock[code] context.stocks.append(stock) print(context.stocks) # before_trading此函数会在每天交易开始前被调用,当天只会被调用一次def before_trading(context, bar_dict): passdef buybuybuy(context,bar_dict): for stock in context.portfolio.positions: order_target_percent(stock,0) #del context.maxvalue[stock] for stock in context.stocks: if bar_dict[stock].is_trading==True: createdic(context,bar_dict,stock) order_target_percent(stock,0.999/len(context.stocks)) pass# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 stoploss(context,bar_dict) pass # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧!
策略名称: | 掷骰子策略 止损 |
---|---|
开始时间: | 2006-06-01 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
楼主这个系列的帖子真不错,精品。多谢楼主。
【止损】 止损/止盈 方案目录 必读
既然这是一个汇总贴, 那么我们就来more academically 地列举一下止损效果吧 。
由于这仅仅是止损策略, 并没有涉及买入操作。 为了让各种自损更加漂亮,我们选取的是15年杠杆牛的那一段时间。
我们选择15 只股票, 首先是不加任何止损的对照组表现 。
可见, 回撤巨大。 不加止损的表现完全取决于股票本身的表现。
''' '''# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import mathimport datetime # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] # 实时打印日志 #scheduler.run_daily(stoploss) logger.info("Interested at stock: " + str(context.to_buy)) scheduler.run_monthly(once,1) context.bb=1 def once(context,bar_dict): if context.bb==1: position(context,bar_dict) context.bb=0 # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! #position(context,bar_dict) #logger.info(type(context.now)) pass def position(context,bar_dict): if len(context.to_buy)!=0: for stock in context.to_buy: order_target_percent(stock,1/len(context.to_buy)) else: order_target_percent(stock,0)
策略名称: | 止损模板 无止损 |
---|---|
开始时间: | 2015-03-02 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
接下来看看时间止损的效果。
recall : 时间止损只能帮助你节约时间的策略。并不能帮你有效的减少回撤。
我们从15 年杠杆牛市看看结果。 可见期初所有的股都因为杠杆而上涨, 所以时间止损并没有触发,而在下跌阶段, 所有的股票都跌倒了时间止损里预设的(1+Y%) 止损线, 所以止损。
'''止损描述: 持股大于 X 天,且区间内回报少于 Y % 止损 使用方法: 0: 设置持股天数 X, 在 init 中 : context.period= X ; 设置区间内回报 Y context.total_return = Y (单位为比例, 非百分比。)1: 复制 def record 和 def stoploss 至script 2: 在下单前 插入 ‘record(context,bar_dict,stock)’ (必须使用for loop 下单)3: 设置 scheduler.run_daily(stopless)''' # 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import datetime import mathimport itertools# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] context.period=10 # 持股天数X context.total_return=0.05 # 持股天数内的回报率 # 实时打印日志 #scheduler.run_daily(stoploss) logger.info("Interested at stock: " + str(context.to_buy)) context.time=pd.DataFrame() #scheduler.run_monthly(rebalance,1) scheduler.run_daily(stoploss) scheduler.run_monthly(once,1) context.bb=1 def once(context,bar_dict): if context.bb==1: rebalance(context,bar_dict) context.bb=0 # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! pass def stoploss( context,bar_dict): # 根据时间 清仓 print(context.time) for stock in context.portfolio.positions: if stock in context.time.columns: buytime=context.time[stock][0] # 获取买入时间 currenttime=context.now.replace(tzinfo=None) # 获取当前时间 print ('buytime='+str(buytime)) print('currenttime='+str(currenttime)) total_return=context.portfolio.positions[stock].market_value/context.portfolio.positions[stock].bought_value # 计算回报 escape=(currenttime-buytime).days # 计算持有天数 if escape>context.period and total_return<1+context.total_return: print(str(stock)+ '大于' + str (context.period)+'天 且回报过小, 卖出') order_target_percent(stock, 0) del context.time[stock] elif total_return>1+context.total_return: print(str(stock)+'回报为: ' +str(total_return)+'大于预设值'+str(1+context.total_return)) else: print(str(stock)+ '持仓未到' +str(context.period)+'天,继续持有') def record(context,bar_dict,stock): if stock not in context.time.columns: temp=pd.DataFrame({str(stock):[context.now.replace(tzinfo=None)]}) logger.info (temp) context.time = pd.concat([context.time, temp], axis=1, join='inner')def rebalance(context,bar_dict): #time=pd.DataFrame() #在买入的同时 创建一个Dataframe 储存买入的时间。 if len(context.to_buy)!=0: for stock in context.to_buy: record(context,bar_dict,stock) order_target_percent(stock,1/len(context.to_buy)) #temp=pd.DataFrame({str(stock):[context.now.replace(tzinfo=None)]}) #logger.info (temp) #time = pd.concat([time, temp], axis=1, join='inner') #context.time=time else: order_target_percent(stock,0)
策略名称: | 时间止损 |
---|---|
开始时间: | 2015-03-01 |
结束时间: | 2015-10-08 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
**限价止损: **
这是一个相对保守的止损方式, 固定某一价格为止损价, 一旦超过这个价位就卖出。
现价止损在杠杆牛时期有较好的表现。 但是缺点就在于其收益是固定的, 存在一个理论最大收益。
'''止损描述: 当前股价大于/小于 某一价格 进行 止盈/止损 使用方法: 0: 在init 中 设置止盈/止损比例, 止损:context.stoplossmultipler= 0.9 #亏损10% 触发止损 止盈:context.stoppofitmultipler= 1.5 #盈利 50% 触发止盈 1: 复制 def stoploss 至script 2: 设置 scheduler.run_daily(stopless)'''# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import datetime # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] context.stoplossmultipler= 0.95 #止损 乘数 context.stoppofitmultipler= 1.4 #止盈 乘数 # 实时打印日志 #scheduler.run_daily(stoploss) logger.info("Interested at stock: " + str(context.to_buy)) scheduler.run_monthly(once,1) context.bb=1 scheduler.run_daily(stoploss) def once(context,bar_dict): if context.bb==1: position(context,bar_dict) context.bb=0 def stoploss(context,bar_dict): for stock in context.portfolio.positions: if bar_dict[stock].last<context.portfolio.positions[stock].average_cost*context.stoplossmultipler:# 现价低于 原价一定比例 order_target_percent(stock,0) print(str(stock)+'跌幅超过'+str((1-context.stoplossmultipler)*100) +'% 触发止损') elif bar_dict[stock].last>context.portfolio.positions[stock].average_cost*context.stoppofitmultipler:# 现价高于原价一定比例 order_target_percent(stock,0) print(str(stock)+'涨幅幅超过'+str((context.stoppofitmultipler-1)*100) +'% 触发止盈') pass # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! #position(context,bar_dict) #logger.info(type(context.now)) pass def position(context,bar_dict): if len(context.to_buy)!=0: for stock in context.to_buy: order_target_percent(stock,1/len(context.to_buy)) else: order_target_percent(stock,0)
策略名称: | 限价止损 |
---|---|
开始时间: | 2015-03-01 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
阶梯止损:
和限价止损不同, 阶梯止损是一个动态的止损方法。 能根据现最高股价调整止损/止盈价位。
虽然做不到完全逃顶,但能在次高位卖出所有股票。
'''止损描述 : 设置初始 止损比例 M , 股价每上涨 X% , 就将止损比例 提高 Y % 本例中:初始止损比例为 -10%。 股价每上涨 10%, 就将止盈比例提高9% 套用方法: 0: 在 init 中设置你的 A X Y 1: 复制‘scheduler.run_daily(stoploss)’ 至 init 2: 复制 def stoploss , def createdic 到策略内3: 在 order 之后加入 createdic(context,bar_dict,stock)'''# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import mathimport datetime # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] context.initSLM=0.9 # 初始止损比例 M context.step=0.10 # 间隔 X context.increment=0.09 # 止损增量 Y context.maxvalue=pd.DataFrame() # 实时打印日志 #scheduler.run_daily(stoploss) logger.info("Interested at stock: " + str(context.to_buy)) scheduler.run_monthly(once,1) context.bb=1 scheduler.run_daily(stoploss) def once(context,bar_dict): if context.bb==1: position(context,bar_dict) context.bb=0 def stoploss(context,bar_dict): for stock in context.portfolio.positions: market_value=context.portfolio.positions[stock].market_value# 该股市场价值 单位(RMB) bought_value=context.portfolio.positions[stock].bought_value#该股初始价值 单位(RMB) stockdic=context.maxvalue[stock] maxvalue=stockdic[0] del context.maxvalue[stock] currSL=context.initSLM*(1+context.increment)**math.floor((math.log(maxvalue/bought_value)/math.log(1+context.step)))#阶梯止损算法 temp=pd.DataFrame({str(stock):[max(maxvalue,market_value),currSL]}) context.maxvalue=pd.concat([context.maxvalue,temp], axis=1, join='inner') # 更新dataframe。 print(str(stock)+'的成本为:' +str( bought_value) +', 最高价值为:'+str(maxvalue)+'现价值为:'+ str(market_value)) print(str(stock) +'的现 止损价位为: ' +str(currSL)) #logger.info ( type(market_value)) #logger.info(type(ontext.maxvalue[stock].values))) if market_value<bought_value*currSL:# 现价初始止损价 order_target_percent(stock,0) #del context.maxvalue[stock] print(str(stock)+ ('触发止损')) '''elif market_value<bought_value*currSL:# 现价低于阶梯止损价 order_target_percent(stock,0) print(str(stock)+ ('触发初始止损')) del context.maxvalue[stock]''' pass # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! #position(context,bar_dict) #logger.info(type(context.now)) pass def createdic(context,bar_dict,stock): if stock not in context.maxvalue.columns: temp=pd.DataFrame({str(stock):[context.portfolio.positions[stock].bought_value,context.initSLM]}) context.maxvalue = pd.concat([context.maxvalue, temp], axis=1, join='inner') print(context.maxvalue) def position(context,bar_dict): if len(context.to_buy)!=0: for stock in context.to_buy: order_target_percent(stock,1/len(context.to_buy)) createdic(context,bar_dict,stock) else: order_target_percent(stock,0)
策略名称: | 阶梯止损 |
---|---|
开始时间: | 2015-03-02 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
跟踪止损:
也是一个动态的止损方法, 就计算量上来说比阶梯止损更cheap。
'''止损描述 : 回撤超过 X% 之后 止损。 套用方法: 0: 在 init 中设置你的 回撤 X context.drawdown = 0.1 % 回撤限度 10%1: 复制‘scheduler.run_daily(stoploss)’ 至 init 2: 复制 def stoploss , def createdic 到策略内3: 在 order 之前加入 createdic(context,bar_dict,stock)'''# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import mathimport datetime # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] context.drawdown= 0.15 # 回撤限度 10% context.maxvalue=pd.DataFrame() # 实时打印日志 #scheduler.run_daily(stoploss) logger.info("Interested at stock: " + str(context.to_buy)) scheduler.run_monthly(once,1) context.bb=1 scheduler.run_daily(stoploss) def once(context,bar_dict): if context.bb==1: position(context,bar_dict) context.bb=0 def stoploss(context,bar_dict): for stock in context.portfolio.positions: market_value=context.portfolio.positions[stock].market_value# 该股市场价值 单位(RMB) bought_value=context.portfolio.positions[stock].bought_value#该股初始价值 单位(RMB) stockdic=context.maxvalue[stock] maxvalue=stockdic[0] del context.maxvalue[stock] #currSP=context.initSPM*(1+math.floor((maxvalue/bought_value-1)/context.step)*context.increment) #阶梯止损算法 例: 该股市值增加10%, 止盈比例提高 5% temp=pd.DataFrame({str(stock):[max(maxvalue,market_value)]}) context.maxvalue=pd.concat([context.maxvalue,temp], axis=1, join='inner') # 更新其盘中最高价值和先阶段比例。 drawdown=1-market_value/max(maxvalue,market_value) print(str(stock)+'的成本为:' +str( bought_value) +', 最高价值为:'+str(maxvalue)+'现价值为:'+ str(market_value)) print(str(stock) +'的现 回撤为: ' +str(drawdown*100)+ '%') #logger.info ( type(market_value)) #logger.info(type(ontext.maxvalue[stock].values))) if drawdown>context.drawdown:# 现价低于 原价一定比例 order_target_percent(stock,0) print(str(stock)+'回撤大于'+ str(context.drawdown*100)+ '%'+' 触发止损') del context.maxvalue[stock] pass # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! #position(context,bar_dict) #logger.info(type(context.now)) pass def createdic(context,bar_dict,stock): if stock not in context.maxvalue.columns: temp=pd.DataFrame({str(stock):[context.portfolio.positions[stock].bought_value]}) context.maxvalue = pd.concat([context.maxvalue, temp], axis=1, join='inner') print(context.maxvalue) def position(context,bar_dict): if len(context.to_buy)!=0: for stock in context.to_buy: order_target_percent(stock,1/len(context.to_buy)) createdic(context,bar_dict,stock) else: order_target_percent(stock,0)
策略名称: | 跟踪止损 |
---|---|
开始时间: | 2015-03-02 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
时间+价差 止损 :
虽然不能帮助你逃顶,但是也算是一个止损方法吧...
'''止损描述: 持股大于 X 天,且区间内回报少于 Y % 止损 若回报大于Y% 则将止损线提高至 1+Y% 使用方法: 0: 设置持股天数 X, 在 init 中 : context.period= X ; 设置区间内回报 Y,在 init 中 : context.increment= Y (单位为比例, 非百分比。)1: 复制 def record 和 def stoploss 至script 2: 在下单前 插入 ‘record(context,bar_dict,stock)’ (必须使用for loop 下单)3: 设置 scheduler.run_daily(stopless)''' # 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import datetime import mathimport itertools# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] context.period=10 # 持股天数X context.increment=0.04 # 实时打印日志 context.time=pd.DataFrame() scheduler.run_monthly(once,1) context.bb=1 scheduler.run_daily(stoploss) def once(context,bar_dict): if context.bb==1: rebalance(context,bar_dict) context.bb=0 # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! pass def stoploss( context,bar_dict): # 根据时间 清仓 print(context.time) for stock in context.portfolio.positions: if stock in context.time.columns: buytime=context.time[stock][0] # 获取买入时间 currenttime=context.now.replace(tzinfo=None) # 获取当前时间 print ('buytime='+str(buytime)) print('currenttime='+str(currenttime)) total_return=context.portfolio.positions[stock].market_value/context.portfolio.positions[stock].bought_value # 计算回报 escape=(currenttime-buytime).days # 计算持有天数 threshold=math.floor(escape/context.period)*context.increment+1 # 计算期望。 if escape>context.period and total_return<threshold: print(str(stock)+ '大于' + str (context.period)+'天 且回报小于'+ str(threshold)+' 卖出') order_target_percent(stock, 0) del context.time[stock] elif total_return>threshold: print(str(stock)+'回报为: ' +str(total_return)+'大于预设值'+str(threshold)+', 继续持有') elif total_return<0.95: print(str(stock)+'周期内跌幅超过5% 直接止损') else: print(str(stock)+ '持仓未到' +str(context.period)+'天,继续持有') def record(context,bar_dict,stock): if stock not in context.time.columns: temp=pd.DataFrame({str(stock):[context.now.replace(tzinfo=None)]}) logger.info (temp) context.time = pd.concat([context.time, temp], axis=1, join='inner')def rebalance(context,bar_dict): #time=pd.DataFrame() #在买入的同时 创建一个Dataframe 储存买入的时间。 if len(context.to_buy)!=0: for stock in context.to_buy: record(context,bar_dict,stock) order_target_percent(stock,1/len(context.to_buy)) else: order_target_percent(stock,0)
策略名称: | 时间+ 价差止损 |
---|---|
开始时间: | 2015-03-01 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
ATR止损 best 止损
'''止损描述 : 计算ATR指标。 若当前价< 持仓最高价-3* ATR : 卖出止损。套用方法: 0: 在 init 中设置你的 moving average ATR 周期: context.ATRperiod=221: 复制‘scheduler.run_daily(stoploss)’ 至 init 2: 复制 def stoploss , def createdic ,def findATR 到策略内3: 在 order 之后加入 createdic(context,bar_dict,stock)'''# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import mathimport talibimport datetime # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] context.ATRperiod=22# ATR 中moving average 的N 值,可自己调, 默认为22 update_universe(context.to_buy) context.trigger=0 context.initSL=0.9 context.profit=0.2 # 当盈利大于20% 就将阶梯设为此价位。 context.maxvalue=pd.DataFrame() # 实时打印日志 #scheduler.run_daily(stoploss) logger.info("Interested at stock: " + str(context.to_buy)) scheduler.run_monthly(once,1) context.bb=1 scheduler.run_daily(stoploss) def once(context,bar_dict): if context.bb==1: position(context,bar_dict) context.bb=0 def findATR(context,bar_dict,stock): # 玄学指标 close=history(context.ATRperiod+2,'1d','close')[stock][0:context.ATRperiod] high=history(context.ATRperiod+2,'1d','high')[stock][1:context.ATRperiod+1] low=history(context.ATRperiod+2,'1d','low')[stock][1:context.ATRperiod+1] art1=high.values-low.values art2=abs(close.values-high.values) art3=abs(close.values-low.values) art123=np.matrix([art1, art2,art3]) rawatr=np.array(art123.max(0)).flatten() ATR=rawatr.sum()/len(rawatr) print(str(rawatr)+'ATR='+str(rawatr)) print(str(stock)+'ATR='+str(ATR)) return ATR def stoploss(context,bar_dict): for stock in context.maxvalue.columns.values: high=bar_dict[stock].high current=bar_dict[stock].last bought_value=context.portfolio.positions[stock].bought_value#该股初始价值 单位(RMB) stockdic=context.maxvalue[stock] highest=stockdic[0] del context.maxvalue[stock] ATR=findATR(context,bar_dict,stock) #currSP=context.initSPM*(1+math.floor((maxvalue/bought_value-1)/context.step)*context.increment) #阶梯止损算法 例: 该股市值增加10%, 止盈比例提高 5% temp=pd.DataFrame({str(stock):[max(highest,high)]}) context.maxvalue=pd.concat([context.maxvalue,temp], axis=1, join='inner') # 更新其盘中最高价值和先阶段比例。 print(str(stock)+'的成本为:' +str( context.portfolio.positions[stock].average_cost) +', 最高价为:'+str(highest)+'ATR为:'+ str(ATR)) if bar_dict[stock].last<highest-3*ATR: print('吊灯止损') order_target_percent(stock,0) del context.maxvalue[stock] #logger.info ( type(market_value)) #logger.info(type(ontext.maxvalue[stock].values))) pass # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! #position(context,bar_dict) #logger.info(type(context.now)) pass def createdic(context,bar_dict,stock): if stock not in context.maxvalue.columns: temp=pd.DataFrame({str(stock):[0]}) context.maxvalue = pd.concat([context.maxvalue, temp], axis=1, join='inner') print(context.maxvalue) def position(context,bar_dict): if len(context.to_buy)!=0: for stock in context.to_buy: createdic(context,bar_dict,stock) order_target_percent(stock,1/len(context.to_buy)) else: order_target_percent(stock,0)
策略名称: | ATR 吊灯止损 |
---|---|
开始时间: | 2015-03-02 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
熔断止损:
一单大盘跌幅超过4% 就 暂停交易20 天。
''' '''# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。import pandas as pd import numpy as np import time import mathimport datetime # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。def init(context): context.to_buy=['600288.XSHG', '600993.XSHG', '000026.XSHE', '600182.XSHG', '600569.XSHG', '002013.XSHE', '600696.XSHG', '000690.XSHE', '600654.XSHG', '600275.XSHG', '600883.XSHG', '600122.XSHG', '000536.XSHE', '600739.XSHG', '600694.XSHG'] # 实时打印日志 #scheduler.run_daily(stoploss) logger.info("Interested at stock: " + str(context.to_buy)) context.circuit=20 # 你想要熔断的天数 context.counter=context.circuit scheduler.run_daily(once) context.bb=1 scheduler.run_daily(stoploss) def stoploss(context,bar_dict): context.counter+=1 b_price= history(10,'1d','close')[context.benchmark] bhigh = history(1,'1d','high')[context.benchmark] blow=history(1,'1d','low')[context.benchmark] if blow.values/bhigh.values<0.96: # 大盘跌幅超过4% 熔断冷静。 for s in context.portfolio.positions: order_target_percent(s,0) context.counter=0 def once(context,bar_dict): if context.counter>context.circuit: position(context,bar_dict) # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新def handle_bar(context, bar_dict): # 开始编写你的主要的算法逻辑 # bar_dict[order_book_id] 可以拿到某个证券的bar信息 # context.portfolio 可以拿到现在的投资组合状态信息 # 使用order_shares(id_or_ins, amount)方法进行落单 # TODO: 开始编写你的算法吧! #position(context,bar_dict) #logger.info(type(context.now)) pass def position(context,bar_dict): if context.counter<context.circuit: print('熔断中') return if len(context.to_buy)!=0: for stock in context.to_buy: order_target_percent(stock,1/len(context.to_buy)) else: order_target_percent(stock,0)
策略名称: | 熔断止损 |
---|---|
开始时间: | 2015-03-02 |
结束时间: | 2016-06-01 |
股票初始资金: | undefined |
回测频率: | 1d |
基准合约: | -- |
佣金倍率: | |
撮合方式: | |
滑点: |
【止损】 止损/止盈 方案目录 必读
@hongbin-zhang 非常感谢楼主分享。楼主图文并茂的讲解,深入浅出,让人如痴如醉。代码与注释齐飞,图像与数字生妙~~~
我在复制研究你的止损方法。有一个小疑问,在度量个股仓位是否亏损的时候,使用的是bought_value与market_value相对大小进行度量。对于bought_value我有一个问题,bought_value是策略中该只股票所有买单总买入价值。仓位在策略执行过程中有增有减,如果按照先入先出的方式理解,先前的卖单其实已经平掉了最前的一部分买单,被平掉的这部分买单成本其实已经是沉默成本了,bought_value度量成本的时候其实包含了这部分沉默成本。
在度量成本时,是否把这些已经平仓部分去掉,只使用未平仓部分的股票买入价进行加权平均计算更为合理呢。假设一种场景,价格走势在大幅波动,最开始买在高位但已经被平仓的股票已经实现了对应的损益,如果后市均价低于之前的话,把这部分买单也计入成本的话,会整体上拉高计算出的成本价,止损线对应也会偏高,这样可能会影响后期利用反弹的行情。
联系客服