止損又叫 “割肉”, 指的是當(dāng)一個投資組合虧損達到一定比例 及時清倉出局, 以免形成更大的虧損的行為。 止盈是指當(dāng)盈利大于一定數(shù)額, 及時獲利了結(jié)。
華爾街有一句話: 讓損失減少,讓利潤飛馳。
我們用一組數(shù)字來說明止損的重要性, 假設(shè)你的資金沒有杠桿,從 10w 虧損至 5w ,資金縮水50%。 但是從5w 增長至10w 需要盈利 100% 才行。假設(shè)你的資金有1:2 的杠桿,若沒有阻止虧損,在虧損達到30%左右,對不起,你爆倉啦。
所以如何賣?在什么時候賣? 是我們必須要深思熟慮的問題。
由于A股市場散戶居多, 無論跌漲都會束手無策。經(jīng)常心里想一套, 手上做一套。 人性的缺點在市場上會被無限放大,這時候就需要程序化交易來彌補人性的缺點。 在百度上隨手一搜都能搜出很多止損方案, 但是這些止損方案可不可行?有什么優(yōu)缺點呢?
在這里提供了幾個簡單的止損方案的模板, 在寫這些代碼的時候考慮了 小白用戶的體驗,用戶只需將相應(yīng)的代碼復(fù)制粘貼到自己的策略中, 并設(shè)置相關(guān)參數(shù)就能順利使用。 詳細調(diào)用方法 請看 源代碼 開頭部分。
為了獲得更好的止損效果, 我建議將調(diào)倉頻率設(shè)置為月調(diào)倉。
接下來是各個止損方案的介紹和地址。
時間止損
時間止損認(rèn)為時間是有價值的,若在一定的時間內(nèi)某股票的回報收益低于一個預(yù)設(shè)值就認(rèn)為該交易低于預(yù)期,選擇賣出。 這是一個非常簡單的止損策略, 由于止損線是固定的, 所以不能很好的減少回撤。若不是專門研究時間止損, 不建議使用。
if 持倉時間> X 天 and 區(qū)間漲幅 小于Y% : 賣出止損else:繼續(xù)持有
詳細地址: https://www.ricequant.com/community/topic/1417
限價止損
限價止損 將買入價設(shè)置為基準(zhǔn)價, 一旦股價上漲大于X% 或下跌大于 Y% 就賣出該股。這是也是一個固定止損/止盈價位的止損方案, 和時間止損存在相同問題:不能有效減少回撤。
if 現(xiàn)價>(1+X%)*買入價:賣出 止盈else if 現(xiàn)價<(1-Y%)*買入價:賣出止損else:繼續(xù)持有
詳細地址: https://www.ricequant.com/community/topic/1419/
跟蹤止損
跟蹤止損 考慮的是該股的回撤, 若回撤大于某預(yù)設(shè)值X% 就將其賣出。 此方案的止損價會隨著最高價的變化而變化, 在股災(zāi)和熔斷中有很好的表現(xiàn)。
X=允許最大回撤if 現(xiàn)價<持股周期內(nèi)最高價*(1-X %):賣出止損else:繼續(xù)持有
詳細地址:https://www.ricequant.com/community/topic/1420
階梯止損
階梯止損是一種 動態(tài)止損策略。 止損價會根據(jù)持股周期內(nèi)最高價的變化而變化。 和跟蹤止損的思路類似, 但是止損價的計算方式略有不同, 股災(zāi)期間表現(xiàn)良好。 但不及階梯止損。
止損價= fx( 買入后最高價, 初始止損價 ,階梯長度,階梯變化率)if 現(xiàn)價< 止損價 :賣出止損else:繼續(xù)持有
詳細地址:https://www.ricequant.com/community/topic/1423
時間+ 階梯 止損
時間+階梯 止損是將“時間有價值” 和 “動態(tài)止損” 這兩個思路結(jié)合在一起的策略。 止損價會隨著 持股周期的變化而變化, 一旦跌破止損價,則賣出。 良好的止損策略。
止損價 =fx ( 持股周期, 期望回報率)if 現(xiàn)價< 止損價:賣出止損
詳細地址 :https://www.ricequant.com/community/topic/1424
ATR 止損
ATR止損 會先計算 一個叫做平均真實波幅 (Average True Range )的指標(biāo),ATR止損是根據(jù)這一指標(biāo)發(fā)散出來編寫的策略。
Raw_ATR=max(|今日振幅|, |昨天收盤-今日最高價|,|昨天收盤-今日最低價|)# 未處理ATR = 這三個指標(biāo)的最大值A(chǔ)TR=moving_average (ATR ,N) #真實ATR 為 Raw_ATR 的N 日簡單移動平均,默認(rèn)N=22
詳細地址:https://www.ricequant.com/community/topic/1429
熔斷止損
如果大盤跌幅過大, 相當(dāng)于檢測到系統(tǒng)性風(fēng)險, 于是賣出所有股票,暫停交易出去旅游。
if 今日最低值/ 今日最高值< 0.96: 清倉止損暫停交易20天
【止損】 止損/止盈 方案目錄 必讀
為了說明止損的重要性, 我特意編寫了一個 擲骰子選股法。
隨機選 15 只股票 ,平均買入 , 每月調(diào)倉。
這是不加任何止損策略的結(jié)果, 可見回撤非常大。
大家也可以克隆一下這個策略,試試手氣, 看看自己的人品怎么樣...
# 可以自己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此函數(shù)會在每天交易開始前被調(diào)用,當(dāng)天只會被調(diào)用一次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# 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 stoploss(context,bar_dict) pass # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用order_shares(id_or_ins, amount)方法進行落單 # TODO: 開始編寫你的算法吧!
策略名稱: | 擲骰子策略 止損 |
---|---|
開始時間: | 2006-06-01 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
樓主這個系列的帖子真不錯,精品。多謝樓主。
【止損】 止損/止盈 方案目錄 必讀
既然這是一個匯總貼, 那么我們就來more academically 地列舉一下止損效果吧 。
由于這僅僅是止損策略, 并沒有涉及買入操作。 為了讓各種自損更加漂亮,我們選取的是15年杠桿牛的那一段時間。
我們選擇15 只股票, 首先是不加任何止損的對照組表現(xiàn) 。
可見, 回撤巨大。 不加止損的表現(xiàn)完全取決于股票本身的表現(xiàn)。
''' '''# 可以自己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 # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用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 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
接下來看看時間止損的效果。
recall : 時間止損只能幫助你節(jié)約時間的策略。并不能幫你有效的減少回撤。
我們從15 年杠桿牛市看看結(jié)果。 可見期初所有的股都因為杠桿而上漲, 所以時間止損并沒有觸發(fā),而在下跌階段, 所有的股票都跌倒了時間止損里預(yù)設(shè)的(1+Y%) 止損線, 所以止損。
'''止損描述: 持股大于 X 天,且區(qū)間內(nèi)回報少于 Y % 止損 使用方法: 0: 設(shè)置持股天數(shù) X, 在 init 中 : context.period= X ; 設(shè)置區(qū)間內(nèi)回報 Y context.total_return = Y (單位為比例, 非百分比。)1: 復(fù)制 def record 和 def stoploss 至script 2: 在下單前 插入 ‘record(context,bar_dict,stock)’ (必須使用for loop 下單)3: 設(shè)置 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 # 持股天數(shù)X context.total_return=0.05 # 持股天數(shù)內(nèi)的回報率 # 實時打印日志 #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 # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用order_shares(id_or_ins, amount)方法進行落單 # TODO: 開始編寫你的算法吧! pass def stoploss( context,bar_dict): # 根據(jù)時間 清倉 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) # 獲取當(dāng)前時間 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 # 計算持有天數(shù) 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)+'大于預(yù)設(shè)值'+str(1+context.total_return)) else: print(str(stock)+ '持倉未到' +str(context.period)+'天,繼續(xù)持有') 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() #在買入的同時 創(chuàng)建一個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 |
結(jié)束時間: | 2015-10-08 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
**限價止損: **
這是一個相對保守的止損方式, 固定某一價格為止損價, 一旦超過這個價位就賣出。
現(xiàn)價止損在杠桿牛時期有較好的表現(xiàn)。 但是缺點就在于其收益是固定的, 存在一個理論最大收益。
'''止損描述: 當(dāng)前股價大于/小于 某一價格 進行 止盈/止損 使用方法: 0: 在init 中 設(shè)置止盈/止損比例, 止損:context.stoplossmultipler= 0.9 #虧損10% 觸發(fā)止損 止盈:context.stoppofitmultipler= 1.5 #盈利 50% 觸發(fā)止盈 1: 復(fù)制 def stoploss 至script 2: 設(shè)置 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 #止損 乘數(shù) context.stoppofitmultipler= 1.4 #止盈 乘數(shù) # 實時打印日志 #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:# 現(xiàn)價低于 原價一定比例 order_target_percent(stock,0) print(str(stock)+'跌幅超過'+str((1-context.stoplossmultipler)*100) +'% 觸發(fā)止損') elif bar_dict[stock].last>context.portfolio.positions[stock].average_cost*context.stoppofitmultipler:# 現(xiàn)價高于原價一定比例 order_target_percent(stock,0) print(str(stock)+'漲幅幅超過'+str((context.stoppofitmultipler-1)*100) +'% 觸發(fā)止盈') pass # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用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 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
階梯止損:
和限價止損不同, 階梯止損是一個動態(tài)的止損方法。 能根據(jù)現(xiàn)最高股價調(diào)整止損/止盈價位。
雖然做不到完全逃頂,但能在次高位賣出所有股票。
'''止損描述 : 設(shè)置初始 止損比例 M , 股價每上漲 X% , 就將止損比例 提高 Y % 本例中:初始止損比例為 -10%。 股價每上漲 10%, 就將止盈比例提高9% 套用方法: 0: 在 init 中設(shè)置你的 A X Y 1: 復(fù)制‘scheduler.run_daily(stoploss)’ 至 init 2: 復(fù)制 def stoploss , def createdic 到策略內(nèi)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)+'現(xiàn)價值為:'+ str(market_value)) print(str(stock) +'的現(xiàn) 止損價位為: ' +str(currSL)) #logger.info ( type(market_value)) #logger.info(type(ontext.maxvalue[stock].values))) if market_value<bought_value*currSL:# 現(xiàn)價初始止損價 order_target_percent(stock,0) #del context.maxvalue[stock] print(str(stock)+ ('觸發(fā)止損')) '''elif market_value<bought_value*currSL:# 現(xiàn)價低于階梯止損價 order_target_percent(stock,0) print(str(stock)+ ('觸發(fā)初始止損')) del context.maxvalue[stock]''' pass # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用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 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
跟蹤止損:
也是一個動態(tài)的止損方法, 就計算量上來說比階梯止損更cheap。
'''止損描述 : 回撤超過 X% 之后 止損。 套用方法: 0: 在 init 中設(shè)置你的 回撤 X context.drawdown = 0.1 % 回撤限度 10%1: 復(fù)制‘scheduler.run_daily(stoploss)’ 至 init 2: 復(fù)制 def stoploss , def createdic 到策略內(nèi)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)+'現(xiàn)價值為:'+ str(market_value)) print(str(stock) +'的現(xiàn) 回撤為: ' +str(drawdown*100)+ '%') #logger.info ( type(market_value)) #logger.info(type(ontext.maxvalue[stock].values))) if drawdown>context.drawdown:# 現(xiàn)價低于 原價一定比例 order_target_percent(stock,0) print(str(stock)+'回撤大于'+ str(context.drawdown*100)+ '%'+' 觸發(fā)止損') del context.maxvalue[stock] pass # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用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 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
時間+價差 止損 :
雖然不能幫助你逃頂,但是也算是一個止損方法吧...
'''止損描述: 持股大于 X 天,且區(qū)間內(nèi)回報少于 Y % 止損 若回報大于Y% 則將止損線提高至 1+Y% 使用方法: 0: 設(shè)置持股天數(shù) X, 在 init 中 : context.period= X ; 設(shè)置區(qū)間內(nèi)回報 Y,在 init 中 : context.increment= Y (單位為比例, 非百分比。)1: 復(fù)制 def record 和 def stoploss 至script 2: 在下單前 插入 ‘record(context,bar_dict,stock)’ (必須使用for loop 下單)3: 設(shè)置 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 # 持股天數(shù)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 # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用order_shares(id_or_ins, amount)方法進行落單 # TODO: 開始編寫你的算法吧! pass def stoploss( context,bar_dict): # 根據(jù)時間 清倉 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) # 獲取當(dāng)前時間 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 # 計算持有天數(shù) 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)+'大于預(yù)設(shè)值'+str(threshold)+', 繼續(xù)持有') elif total_return<0.95: print(str(stock)+'周期內(nèi)跌幅超過5% 直接止損') else: print(str(stock)+ '持倉未到' +str(context.period)+'天,繼續(xù)持有') 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() #在買入的同時 創(chuàng)建一個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 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
ATR止損 best 止損
'''止損描述 : 計算ATR指標(biāo)。 若當(dāng)前價< 持倉最高價-3* ATR : 賣出止損。套用方法: 0: 在 init 中設(shè)置你的 moving average ATR 周期: context.ATRperiod=221: 復(fù)制‘scheduler.run_daily(stoploss)’ 至 init 2: 復(fù)制 def stoploss , def createdic ,def findATR 到策略內(nèi)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 值,可自己調(diào), 默認(rèn)為22 update_universe(context.to_buy) context.trigger=0 context.initSL=0.9 context.profit=0.2 # 當(dāng)盈利大于20% 就將階梯設(shè)為此價位。 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): # 玄學(xué)指標(biāo) 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 # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用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 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
熔斷止損:
一單大盤跌幅超過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 # 你想要熔斷的天數(shù) 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) # 你選擇的證券的數(shù)據(jù)更新將會觸發(fā)此段邏輯,例如日或分鐘歷史數(shù)據(jù)切片或者是實時數(shù)據(jù)切片更新def handle_bar(context, bar_dict): # 開始編寫你的主要的算法邏輯 # bar_dict[order_book_id] 可以拿到某個證券的bar信息 # context.portfolio 可以拿到現(xiàn)在的投資組合狀態(tài)信息 # 使用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 |
結(jié)束時間: | 2016-06-01 |
股票初始資金: | undefined |
回測頻率: | 1d |
基準(zhǔn)合約: | -- |
傭金倍率: | |
撮合方式: | |
滑點: |
【止損】 止損/止盈 方案目錄 必讀
@hongbin-zhang 非常感謝樓主分享。樓主圖文并茂的講解,深入淺出,讓人如癡如醉。代碼與注釋齊飛,圖像與數(shù)字生妙~~~
我在復(fù)制研究你的止損方法。有一個小疑問,在度量個股倉位是否虧損的時候,使用的是bought_value與market_value相對大小進行度量。對于bought_value我有一個問題,bought_value是策略中該只股票所有買單總買入價值。倉位在策略執(zhí)行過程中有增有減,如果按照先入先出的方式理解,先前的賣單其實已經(jīng)平掉了最前的一部分買單,被平掉的這部分買單成本其實已經(jīng)是沉默成本了,bought_value度量成本的時候其實包含了這部分沉默成本。
在度量成本時,是否把這些已經(jīng)平倉部分去掉,只使用未平倉部分的股票買入價進行加權(quán)平均計算更為合理呢。假設(shè)一種場景,價格走勢在大幅波動,最開始買在高位但已經(jīng)被平倉的股票已經(jīng)實現(xiàn)了對應(yīng)的損益,如果后市均價低于之前的話,把這部分買單也計入成本的話,會整體上拉高計算出的成本價,止損線對應(yīng)也會偏高,這樣可能會影響后期利用反彈的行情。
聯(lián)系客服