1 # 根據缺口的模式選股買股票 2 ''' 3 -------------------------------------------- 4 一、整體回測前要作的事情 5 initialize(context) 6 1.一、設置策略參數 ----> 全局常量 7 1.二、設置中間變量 ----> 全局變量 8 1.三、設置回測條件 ----> JoinQuant額外須要的 9 二、天天開盤前選股策略 (下面策略,發現這種股,不容錯過) 10 2.一、設置手續費 11 2.二、設置可行股票池,好比過濾當日停牌股票 12 2.三、篩選上市滿一年的所有A股 13 2.四、篩選上市發生向上缺口的時點 14 定義爲:今日最低價>昨日最高價,刪除漲停的個股 15 漲幅>5% 16 2.五、篩選前期盤整階段,好比20-30個交易日,最高價-最低價/最低價<15%或者標準差較少的 17 2.六、缺口當日成交量 > 前20個交易日平均成交量的50%,也就是15倍以上。 18 三、天天交易時 19 3.一、買入/賣出信號判斷 20 3.二、執行買入/賣出的操做 21 四、天天收盤 22 無 23 24 -------------------------------------------- 25 關於何時賣? 26 策略有三,第一個就是設置止盈位。也就是不須要追求最高點賣出。 27 好比你設置一個從最近高點下滑3%(比例自調)的位置做爲賣出點。 28 第二個就是利用技術分析,看重要的壓力位,一方面是均線系統的壓力, 29 要看的是日線,周線月線,週期越大,壓力越強,其次是前期的高點, 30 密集成交區,這個區域是深度套牢區,所以能夠暫時止盈。 31 還有就是識技術指標的圖,好比看MACD頂背離,這個比較準,KDJ超賣等等。 32 建議多去分析大盤,80%的股票和大盤會保存同樣走勢,大盤觸頂,個股通常也好不到哪去。 33 第三就是關注基本面,同行對比,分析當前的股價的PE,以及與同行業的公司來看, 34 好比營業總收入排第幾,淨利潤排第幾,收入增速排第幾,它的總市值排在第幾。 35 若是基本面排在行業第10,可是市值排在第一,這就表示高估了。能夠擇機止盈。 36 37 ''' 38 39 40 # 41 import jqdata 42 import pandas as pd 43 import datetime as dt 44 import time 45 46 ''' 47 ================================================================================ 48 整體回測前 49 ================================================================================ 50 ''' 51 # 初始化函數,設定基準等等 52 def initialize(context): 53 print '初始化方法' 54 set_params() # 設置策略常量 55 set_variables() # 設置中間變量 56 set_backtest() # 設置回測條件 57 print '--------------------------------------' 58 59 #1 60 #設置策略參數 61 def set_params(): 62 print '設置策略參數' 63 g.tc = 15 # 調倉天數 64 g.num_stocks = 10 # 每次調倉選取的最大股票數量 65 66 #2 67 #設置中間變量 68 def set_variables(): 69 print '設置中間變量' 70 g.t = 0 # 記錄回測運行的天數 71 g.if_trade = False # 當天是否交易 72 73 #3 74 #設置回測條件 75 def set_backtest(): 76 print '設置回測條件' 77 78 # 設定滬深300做爲基準,就是基準收益 79 set_benchmark('000300.XSHG') 80 81 82 # 開啓動態復權模式(真實價格) 83 set_option('use_real_price', True) 84 # 輸出內容到日誌 log.info() 85 log.info('初始函數開始運行且全局只運行一次') 86 # 過濾掉order系列API產生的比error級別低的log 87 # log.set_level('order', 'error') 88 89 ### 股票相關設定 ### 90 # 股票類每筆交易時的手續費是:買入時佣金萬分之三,賣出時佣金萬分之三加千分之一印花稅, 每筆交易佣金最低扣5塊錢 91 set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock') 92 93 ## 運行函數(reference_security爲運行時間的參考標的;傳入的標的只作種類區分,所以傳入'000300.XSHG'或'510300.XSHG'是同樣的) 94 # 開盤前運行 95 run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') 96 # 開盤時運行 97 run_daily(market_open, time='every_bar', reference_security='000300.XSHG') 98 # 收盤後運行 99 run_daily(after_market_close, time='after_close', reference_security='000300.XSHG') 100 101 log.set_level('order','error') # 設置報錯等級 102 103 ''' 104 ================================================================================ 105 天天開盤前 106 ================================================================================ 107 二、天天開盤前選股策略 (下面策略,發現這種股,不容錯過) 108 2.一、設置手續費 109 2.二、設置可行股票池,好比過濾當日停牌股票 110 2.三、篩選上市滿一年的所有A股 111 2.四、篩選上市發生向上缺口的時點 112 定義爲:今日最低價>昨日最高價,刪除漲停的個股 113 漲幅>5% 114 2.五、篩選前期盤整階段,好比20-30個交易日,最高價-最低價/最低價<15%或者標準差較少的 115 2.六、缺口當日成交量 > 前20個交易日平均成交量的50%,也就是15倍以上。 116 ''' 117 ## 開盤前運行函數 118 def before_market_open(context): 119 # 輸出運行時間 120 log.info('函數運行時間(before_market_open):'+str(context.current_dt.time())) 121 122 print '----天天開盤前要作的事情----' 123 124 set_slip_fee(context) # 設置滑點與手續費 125 # g.stocks=get_index_stocks('000300.XSHG') # 設置滬深300爲初始股票池 126 g.stocks=get_index_stocks('000002.XSHG') # 設置000002.XSHG所有上市A股 127 # 設置可行股票池 128 g.feasible_stocks = set_feasible_stocks(g.stocks,context) 129 130 131 # 給微信發送消息(添加模擬交易,並綁定微信生效) 132 # send_message('美好的一天~') 133 134 # 要操做的股票:平安銀行(g.爲全局變量) 135 # g.security = '000001.XSHE' 136 137 # 138 # 設置可行股票池:過濾掉當日停牌的股票 139 # 輸入:initial_stocks爲list類型,表示初始股票池; context(見API) 140 # 輸出:unsuspened_stocks爲list類型,表示當日未停牌的股票池,即:可行股票池 141 def set_feasible_stocks(initial_stocks,context): 142 # 判斷初始股票池的股票是否停牌,返回list 143 # print '設置可行股票池:過濾掉當日停牌的股票',context.current_dt.day 144 # print '當前時期%10s' %(context.current_dt.strftime("%Y-%m-%d")) 145 paused_info = []# 存儲對應股票是否停牌的信息數組 146 liste_Date_info = []# 存儲對應的上市時間 147 # 在股票基本信息表 - STK_STOCKINFO能找到 148 stock_info = get_all_securities(['stock']); 149 150 151 # get_current_data ♠ - 獲取當前時間數據 152 current_data = get_current_data() 153 print '打印--',initial_stocks 154 print '再打印--當前時間數據對象返回是空的',current_data 155 156 for i in initial_stocks: 157 # i是遍歷出來的每一個股票的代碼 158 # 而後paused是判斷這個股票是否停牌,False表示沒有停牌 159 paused_info.append(current_data[i].paused) 160 161 # print '獲取全部股票數據',stock_info[i].start_date 162 # 如何獲取上市滿一年的股票 163 # 先獲取全部股票數據 .start_data 164 # print '當前時期:%10s--股票上市時期:%10s' %(context.current_dt.strftime("%Y-%m-%d"),stock_info.at[i,'start_date']) 165 # print '當前時期:%10s--股票上市時期' %((stock_info.at[i,'start_date']-context.current_dt).days) 166 # 存儲上市時間是否滿一年,若是滿一年爲YES 167 isGoPublicOneYear = calculate_goPublick_OneYear(context.current_dt.strftime("%Y-%m-%d"),str(stock_info.at[i,'start_date'])) 168 liste_Date_info.append(isGoPublicOneYear) 169 if isGoPublicOneYear == False: 170 print '上市不滿一年的股票%10s:%10s' %(i,stock_info.at[i,'display_name']) 171 172 173 df_paused_public_info = pd.DataFrame({'paused_info':paused_info,'liste_Date_info':liste_Date_info},index = initial_stocks) 174 # print 'df_paused_public_info:\n',df_paused_public_info 175 unsuspened_stocks = list(df_paused_public_info.index[(df_paused_public_info.paused_info == False) and (df_paused_public_info.liste_Date_info == True)]) 176 177 # print '最後得到的index',unsuspened_stocks 178 179 180 181 182 return unsuspened_stocks 183 184 # 計算當天交易時間是否爲上市時間滿一年 185 def calculate_goPublick_OneYear(currentTime,goPublicTime): 186 currentTimeDate = time.strptime(currentTime,"%Y-%m-%d") 187 y,m,d = currentTimeDate[0:3] 188 189 goPublicTimeDate = time.strptime(goPublicTime,"%Y-%m-%d") 190 y2,m2,d2 = goPublicTimeDate[0:3] 191 192 # print (dt.datetime(y,m,d)-dt.datetime(y2,m2,d2)).days 193 194 if ((dt.datetime(y,m,d)-dt.datetime(y2,m2,d2)).days)>366: 195 return True 196 else: 197 return False 198 199 200 #5 201 # 根據不一樣的時間段設置滑點與手續費 202 # 輸入:context(見API) 203 # 輸出:none 204 def set_slip_fee(context): 205 print '根據不一樣的時間段設置滑點與手續費' 206 # 將滑點設置爲0 207 set_slippage(FixedSlippage(0)) 208 # 根據不一樣的時間段設置手續費 209 print '根據不一樣的時間段設置手續費' 210 dt=context.current_dt 211 if dt>datetime.datetime(2013,1, 1): 212 set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0013, min_cost=5)) 213 214 elif dt>datetime.datetime(2011,1, 1): 215 set_commission(PerTrade(buy_cost=0.001, sell_cost=0.002, min_cost=5)) 216 217 elif dt>datetime.datetime(2009,1, 1): 218 set_commission(PerTrade(buy_cost=0.002, sell_cost=0.003, min_cost=5)) 219 else: 220 set_commission(PerTrade(buy_cost=0.003, sell_cost=0.004, min_cost=5)) 221 222 223 ''' 224 ================================================================================ 225 天天交易時 226 ================================================================================ 227 ''' 228 ## 開盤時運行函數 229 def market_open(context): 230 log.info('函數運行時間(market_open):'+str(context.current_dt.time())) 231 security = g.security 232 # 獲取股票的收盤價 233 close_data = attribute_history(security, 5, '1d', ['close']) 234 # 取得過去五天的平均價格 235 MA5 = close_data['close'].mean() 236 # 取得上一時間點價格 237 current_price = close_data['close'][-1] 238 # 取得當前的現金 239 cash = context.portfolio.available_cash 240 241 # 若是上一時間點價格高出五天平均價1%, 則全倉買入 242 if current_price > 1.01*MA5: 243 # 記錄此次買入 244 log.info("價格高於均價 1%%, 買入 %s" % (security)) 245 # 用全部 cash 買入股票 246 # order_value(security, cash) 247 # 若是上一時間點價格低於五天平均價, 則空倉賣出 248 elif current_price < MA5 and context.portfolio.positions[security].closeable_amount > 0: 249 # 記錄此次賣出 250 log.info("價格低於均價, 賣出 %s" % (security)) 251 # 賣出全部股票,使這隻股票的最終持有量爲0 252 # order_target(security, 0) 253 254 ''' 255 ================================================================================ 256 天天收盤後 257 ================================================================================ 258 ''' 259 260 ## 收盤後運行函數 261 def after_market_close(context): 262 log.info(str('函數運行時間(after_market_close):'+str(context.current_dt.time()))) 263 #獲得當天全部成交記錄 264 trades = get_trades() 265 for _trade in trades.values(): 266 log.info('成交記錄:'+str(_trade)) 267 log.info('一天結束') 268 log.info('##############################################################')