最近在研究的聚寬策略,一般技術分析的我直接轉qmt了,財務因子有一點麻煩,我直接利用我開發強大的服務器系統,直接讀取信號,最近在優化一下系統,最近在開發對接bigquant的交易系統,完成了api數據的對接
文章
聚寬策略----國九條后中小板微盤小改,年化135.40%https://mp.weixin.qq.com/s/a01ilT05Dye4uIvjui7W-Q
高速服務器?http://101.34.65.108:8888/
聚寬設置只需要輸入策略的授權碼就可以
授權碼:小果新國九條小市值策略
可以服務器查詢授權碼是否注冊,可以找我注冊,授權碼必須唯一,一個策略一個,沒有問題
點擊測試可以看回測數據
回測數據
交易數據
服務器接受的數據,輸入授權碼就可以:小果新國九條小市值策略
數據全部存在了數據庫
實盤設置參考實盤,先設置測試模式,文章里面有說明
測試時候的設置輸入賬戶
輸入策略授權碼,多策略用逗號隔開
測試時候的參數設置全部在text里面改
text={
"賬戶":"40018483",
"賬戶支持融資融券":"賬戶支持融資融券,賬戶類型STOCK/CREDIT",
"賬戶類型":"STOCK",
"買入價格編碼":5,
"賣出價格編碼":5,
"黑名單說明":"黑名單里面的標的,不會買入也不會賣出",
"黑名單":['600031.SH','600111.SH','513100.SH'],
"聚寬跟單":"跟單原理",
"服務器設置":"服務器跟單設置",
"服務器":"http://101.34.65.108",
"端口":"8888",
"服務器編碼":"63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad",
"測試說明":"開啟測試就是選擇歷史交易不開啟就是選擇今天的數據",
"是否開啟測試":"是",
"測試數量":200,
"跟單設置":"跟單設置***********",
"賬戶跟單比例":0.5,
"多策略用逗號隔開":"多策略用逗號隔開********",
"組合名稱":["小果新國九條小市值策略"],
"組合授權碼":["小果新國九條小市值策略"],
"組合跟單比例":[1],
"不同策略間隔更新時間":0,
"下單默認說明":"默認/金額/數量",
"下單模式":"默認",
"下單值":1000,
"時間設置":"時間設置********",
"交易時間段":8,
"交易開始時間":0,
"交易結束時間":24,
"是否參加集合競價":"否",
"開始交易分鐘":0,
"是否開啟臨時id記錄":"否"
}
點擊測試看看
測試沒有問題直接掛模型交易實盤
點擊運行
策略的交易數據
交易數據
測試沒有問題把參數改成實盤就可以,是否測試參數改成否,開啟臨時id記錄
實盤參數設置
實盤參數設置
text={
"賬戶":"40018483",
"賬戶支持融資融券":"賬戶支持融資融券,賬戶類型STOCK/CREDIT",
"賬戶類型":"STOCK",
"買入價格編碼":5,
"賣出價格編碼":5,
"黑名單說明":"黑名單里面的標的,不會買入也不會賣出",
"黑名單":['600031.SH','600111.SH','513100.SH'],
"聚寬跟單":"跟單原理",
"服務器設置":"服務器跟單設置",
"服務器":"http://101.34.65.108",
"端口":"8888",
"服務器編碼":"63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad",
"測試說明":"開啟測試就是選擇歷史交易不開啟就是選擇今天的數據",
"是否開啟測試":"否",
"測試數量":200,
"跟單設置":"跟單設置***********",
"賬戶跟單比例":0.5,
"多策略用逗號隔開":"多策略用逗號隔開********",
"組合名稱":["小果新國九條小市值策略"],
"組合授權碼":["小果新國九條小市值策略"],
"組合跟單比例":[1],
"不同策略間隔更新時間":0,
"下單默認說明":"默認/金額/數量",
"下單模式":"默認",
"下單值":1000,
"時間設置":"時間設置********",
"交易時間段":8,
"交易開始時間":0,
"交易結束時間":24,
"是否參加集合競價":"否",
"開始交易分鐘":0,
"是否開啟臨時id記錄":"是"
}
重新啟動策略就可以
實時更新分析數據
當然我也有miniqmt版本掛服務器24小時運行就是比較復雜
源代碼我全部上傳知識星球了可以加入直接下載不懂的問我就可以量化支持
加我備注入群可以加入量化群
聚寬源代碼
??????????????
# 標題:國九條后中小板微盤小改,年化135.40%
#小果新國九條小市值策略
#小果新國九條小市值策略
'''
小果聚寬跟單系統
原理替代,繼承聚寬的交易函數類
讀取下單類的函數參數把交易數據發送到服務器
把下面的全部源代碼復制到聚寬策略的開頭就可以
實盤前先模擬盤測試一下數據
把下面的內容全部復制到策略的開頭就可以
作者微信15117320079
'''
import?requests
import?json
import?pandas?as?pd
from?jqdata?import?*
url='http://101.34.65.108'
port=8888
#自定義服務器編碼
url_code='63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad'
#記得把這個改成自己的一個策略一個,策略的名稱找作者建立
password='小果新國九條小市值策略'
class?joinquant_trader:
? ??def?__init__(self,url='http://101.34.65.108',
? ? ? ? ? ? ? ? port=8888,
? ? ? ? ? ? ? ? url_code='63d85b6189e42cba63feea36381da615c31ad8e36ae420ed67f60f3598efc9ad',
? ? ? ? ? ? ? ? password='123456'):
? ? ? ??'''
? ? ? ? 獲取服務器數據
? ? ? ? '''
? ? ? ? self.url=url
? ? ? ? self.port=port
? ? ? ? self.url_code=url_code
? ? ? ? self.password=password
? ??def?get_user_data(self,data_type='用戶信息'):
? ? ? ??'''
? ? ? ? 獲取使用的數據
? ? ? ? data_type='用戶信息','實時數據',歷史數據','清空實時數據','清空歷史數據'
? ? ? ? '''
? ? ? ? url='{}:{}/_dash-update-component'.format(self.url,self.port)
? ? ? ? headers={'Content-Type':'application/json'}
? ? ? ? data={"output":"joinquant_trader_table.data@{}".format(self.url_code),
? ? ? ? ? ??"outputs":{"id":"joinquant_trader_table","property":"data@{}".format(self.url_code)},
? ? ? ? ? ??"inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_data_type","property":"value","value":data_type},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_text","property":"value","value":"\n ? ? ? ? ? ? ? {'狀態': 'held', '訂單添加時間': 'datetime.datetime(2024, 4, 23, 9, 30)', '買賣': 'False', '下單數量': '9400', '已經成交': '9400', '股票代碼': '001.XSHE', '訂單ID': '1732208241', '平均成交價格': '10.5', '持倉成本': '10.59', '多空': 'long', '交易費用': '128.31'}\n ? ? ? ? ? ? ? ?"},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_run","property":"value","value":"運行"},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_down_data","property":"value","value":"不下載數據"}],
? ? ? ? ? ? ? ? ? ??"changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]}
? ? ? ? res=requests.post(url=url,data=json.dumps(data),headers=headers)
? ? ? ? text=res.json()
? ? ? ? df=pd.DataFrame(text['response']['joinquant_trader_table']['data'])
? ? ? ??return?df
? ??def?send_order(self,result):
? ? ? ??'''
? ? ? ? 發送交易數據
? ? ? ? '''
? ? ? ? url='{}:{}/_dash-update-component'.format(self.url,self.port)
? ? ? ? headers={'Content-Type':'application/json'}
? ? ? ? data={"output":"joinquant_trader_table.data@{}".format(self.url_code),
? ? ? ? ? ??"outputs":{"id":"joinquant_trader_table","property":"data@{}".format(self.url_code)},
? ? ? ? ? ??"inputs":[{"id":"joinquant_trader_password","property":"value","value":self.password},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_data_type","property":"value","value":'實時數據'},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_text","property":"value","value":result},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_run","property":"value","value":"運行"},
? ? ? ? ? ? ? ? ? ? {"id":"joinquant_trader_down_data","property":"value","value":"不下載數據"}],
? ? ? ? ? ? ? ? ? ??"changedPropIds":["joinquant_trader_run.value"],"parsedChangedPropsIds":["joinquant_trader_run.value"]}
? ? ? ? res=requests.post(url=url,data=json.dumps(data),headers=headers)
? ? ? ? text=res.json()
? ? ? ? df=pd.DataFrame(text['response']['joinquant_trader_table']['data'])
? ? ? ??return?df
#繼承類
xg_data=joinquant_trader(url=url,port=port,password=password,url_code=url_code)
def?send_order(result):
? ??'''
? ? 發送函數
? ? status: 狀態, 一個OrderStatus值
? ? add_time: 訂單添加時間, [datetime.datetime]對象
? ? is_buy: bool值, 買還是賣,對于期貨:
? ? 開多/平空 -> 買
? ? 開空/平多 -> 賣
? ? amount: 下單數量, 不管是買還是賣, 都是正數
? ? filled: 已經成交的股票數量, 正數
? ? security: 股票代碼
? ? order_id: 訂單ID
? ? price: 平均成交價格, 已經成交的股票的平均成交價格(一個訂單可能分多次成交)
? ? avg_cost: 賣出時表示下賣單前的此股票的持倉成本, 用來計算此次賣出的收益. 買入時表示此次買入的均價(等同于price).
? ? side: 多/空,'long'/'short'
? ? action: 開/平, 'open'/'close'
? ? commission交易費用(傭金、稅費等)
? ? '''
? ? data={}
? ? data['狀態']=str(result.status)
? ? data['訂單添加時間']=str(result.add_time)
? ? data['買賣']=str(result.is_buy)
? ? data['下單數量']=str(result.amount)
? ? data['已經成交']=str(result.filled)
? ? data['股票代碼']=str(result.security)
? ? data['訂單ID']=str(result.order_id)
? ? data['平均成交價格']=str(result.price)
? ? data['持倉成本']=str(result.avg_cost)
? ? data['多空']=str(result.side)
? ? data['交易費用']=str(result.commission)
? ? result=str(data)
? ? xg_data.send_order(result)
? ??return?data
def?xg_order(func):
? ??'''
? ? 繼承order對象 數據交易函數
? ? '''
? ??def?wrapper(*args, **kwargs):
? ? ? ? result = func(*args, **kwargs)
? ? ? ??if?result ==?None:
? ? ? ? ? ??return
? ? ? ? send_order(result)
? ? ? ??return?result
? ??return?wrapper
def?xg_order_target(func):
? ??'''
? ? 繼承order_target對象 百分比
? ? '''
? ??def?wrapper(*args, **kwargs):
? ? ? ? result = func(*args, **kwargs)
? ? ? ??if?result ==?None:
? ? ? ? ? ??return? ? ? ??
? ? ? ? send_order(result)
? ? ? ??return?result
? ??return?wrapper
def?xg_order_value(func):
? ??'''
? ? 繼承order_value對象 數量
? ? '''
? ??def?wrapper(*args, **kwargs):
? ? ? ? result = func(*args, **kwargs)
? ? ? ??if?result ==?None:
? ? ? ? ? ??return? ? ? ??
? ? ? ? send_order(result)
? ? ? ??return?result
? ??return?wrapper
def?xg_order_target_value(func):
? ??'''
? ? 繼承order_target_value對象 數量
? ? '''
? ??def?wrapper(*args, **kwargs):
? ? ? ? result = func(*args, **kwargs)
? ? ? ??if?result ==?None:
? ? ? ? ? ??return? ? ? ??
? ? ? ? send_order(result)
? ? ? ??return?result
? ??return?wrapper
order = xg_order(order)
order_target = xg_order_target(order_target)
order_value = xg_order_value(order_value)
order_target_value = xg_order_target_value(order_target_value)
from?jqdata?import?*
from?jqfactor?import?*
import?numpy?as?np
import?pandas?as?pd
from?datetime?import?time,date
from?jqdata?import?finance
#初始化函數?
def?initialize(context):
? ??# 開啟防未來函數
? ? set_option('avoid_future_data',?True)
? ??# 成交量設置
? ??#set_option('order_volume_ratio', 0.10)
? ??# 設定基準
? ? set_benchmark('399101.XSHE')
? ??# 用真實價格交易
? ? set_option('use_real_price',?True)
? ??# 將滑點設置為0
? ? set_slippage(FixedSlippage(3/10000))
? ??# 設置交易成本萬分之三,不同滑點影響可在歸因分析中查看
? ? set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=2.5/10000, close_commission=2.5/10000, close_today_commission=0, min_commission=5),type='stock')
? ??# 過濾order中低于error級別的日志
? ? log.set_level('order',?'error')
? ? log.set_level('system',?'error')
? ? log.set_level('strategy',?'debug')
? ??#初始化全局變量 bool
? ? g.trading_signal =?True??# 是否為可交易日
? ? g.run_stoploss =?True??# 是否進行止損
? ? g.filter_audit =?False??# 是否篩選審計意見
? ? g.adjust_num =?True??# 是否調整持倉數量
? ??#全局變量list
? ? g.hold_list = []?#當前持倉的全部股票 ? ?
? ? g.yesterday_HL_list = []?#記錄持倉中昨日漲停的股票
? ? g.target_list = []
? ? g.pass_months = [1,?4] ?# 空倉的月份
? ? g.limitup_stocks = [] ??# 記錄漲停的股票避免再次買入
? ??#全局變量float/str
? ? g.min_mv =?10??# 股票最小市值要求
? ? g.max_mv =?100??# 股票最大市值要求
? ? g.stock_num =?4??# 持股數量
? ? g.stoploss_list = [] ?# 止損賣出列表
? ? g.other_sale ? ?= [] ?# 其他賣出列表
? ? g.stoploss_strategy =?3??# 1為止損線止損,2為市場趨勢止損, 3為聯合1、2策略
? ? g.stoploss_limit =?0.09??# 止損線
? ? g.stoploss_market =?0.05??# 市場趨勢止損參數
? ? g.highest =?50??# 股票單價上限設置
? ? g.money_etf =?'511880.XSHG'??# 空倉月份持有銀華日利ETF
? ??# 設置交易運行時間
? ? run_daily(prepare_stock_list,?'9:05')
? ? run_daily(trade_afternoon, time='14:00', reference_security='399101.XSHE')?#檢查持倉中的漲停股是否需要賣出
? ? run_daily(stop_loss, time='10:00')?# 止損函數
? ? run_daily(close_account,?'14:50')
? ? run_weekly(weekly_adjustment,2,'10:00')
? ??#run_weekly(print_position_info, 5, time='15:10', reference_security='000300.XSHG')
#1-1 準備股票池
def?prepare_stock_list(context):
? ??#獲取已持有列表
? ? g.limitup_stocks = []
? ? g.hold_list =?list(context.portfolio.positions)
? ??#獲取昨日漲停列表
? ??if?g.hold_list:
? ? ? ? df = get_price(g.hold_list, end_date=context.previous_date, frequency='daily', fields=['close','high_limit','low_limit'], count=1, panel=False, fill_paused=False)
? ? ? ? df = df[df['close'] == df['high_limit']]
? ? ? ? g.yesterday_HL_list = df['code'].tolist()
? ??else:
? ? ? ? g.yesterday_HL_list = []
? ??#判斷今天是否為賬戶資金再平衡的日期
? ? g.trading_signal = today_is_between(context)
#1-2 選股模塊
def?get_stock_list(context):
? ? final_list = []
? ? MKT_index =?'399101.XSHE'
? ? initial_list = filter_stocks(context, get_index_stocks(MKT_index))
? ??# 國九更新:過濾近一年凈利潤為負且營業收入小于1億的
? ??# 國九更新:過濾近一年期末凈資產為負的 (經查詢沒有為負數的,所以直接pass這條)
? ??# 國九更新:過濾近一年審計建議無法出具或者為負面建議的 (經過凈利潤等篩選,審計意見幾乎不會存在異常)
? ? q = query(
? ? ? ? valuation.code,
? ? ).filter(
? ? ? ? valuation.code.in_(initial_list),
? ? ? ? valuation.market_cap.between(g.min_mv,g.max_mv), ?# 總市值 circulating_market_cap/market_cap 單位:億元
? ? ? ? income.np_parent_company_owners >?0, ??# 歸屬于母公司所有者的凈利潤(元)
? ? ? ? income.net_profit >?0, ?# 凈利潤(元)
? ? ? ? income.operating_revenue >?1e8??# 營業收入 (元)
? ? ).order_by(valuation.market_cap.asc()).limit(g.stock_num*3)
? ? df = get_fundamentals(q)
? ??# 如果篩選審計意見會大幅度增加回測時長,實測增加此項篩選不影響選股
? ??if?g.filter_audit:
? ? ? ? before_audit_filter =?len(df)
? ? ? ? df['audit'] = df['code'].apply(lambda?x: filter_audit(context, x))
? ? ? ? df_audit = df[df['audit'] ==?True]
? ? ? ? log.info('去除掉了存在審計問題的股票{}只'.format(len(df)-before_audit_filter))
? ? final_list = df['code'].tolist()
? ??if?final_list:
? ? ? ? last_prices = history(1, unit='1d', field='close', security_list=final_list)
? ? ? ??return?[stock?for?stock?in?final_list?if?stock?in?g.hold_list?or?last_prices[stock][-1] <= g.highest]
? ??else:
? ? ? ??# 由于有時候選股條件苛刻,所以會沒有股票入選,這時買入銀華日利ETF
? ? ? ? log.info('無適合股票,買入ETF')
? ? ? ??return?[g.money_etf] ? ? ? ?
#1-3 整體調整持倉
def?weekly_adjustment(context):
? ??if?g.trading_signal:
? ? ? ??if?g.adjust_num:
? ? ? ? ? ? new_num = adjust_stock_num(context)
? ? ? ? ? ? g.stock_num = new_num
? ? ? ? ? ? log.info(f'持倉數量修改為{new_num}')
? ? ? ? g.target_list = get_stock_list(context)[:g.stock_num]
? ? ? ? log.info(str(g.target_list))
? ? ? ? sell_list = [stock?for?stock?in?g.hold_list?if?stock?not?in?g.target_list?and?stock?not?in?g.yesterday_HL_list]
? ? ? ? hold_list = [stock?for?stock?in?g.hold_list?if?stock?in?g.target_list?or?stock?in?g.yesterday_HL_list]
? ? ? ? log.info("賣出[%s]"?% (str(sell_list)))
? ? ? ? log.info("已持有[%s]"?% (str(hold_list)))
? ? ? ??for?stock?in?sell_list:
? ? ? ? ? ? order_target_value(stock,?0)
? ? ? ? buy_list = [stock?for?stock?in?g.target_list?if?stock?not?in?g.hold_list]
? ? ? ? buy_security(context, buy_list,len(buy_list))
? ??else:
? ? ? ? buy_security(context, [g.money_etf],1)
? ? ? ? log.info('該月份為空倉月份,持有銀華日利ETF')
#1-4 調整昨日漲停股票
def?check_limit_up(context):
? ? now_time = context.current_dt
? ??if?g.yesterday_HL_list != []:
? ? ? ??#對昨日漲停股票觀察到尾盤如不漲停則提前賣出,如果漲停即使不在應買入列表仍暫時持有
? ? ? ??for?stock?in?g.yesterday_HL_list:
? ? ? ? ? ? current_data = get_price(stock, end_date=now_time, frequency='1m', fields=['close','high_limit'], skip_paused=False, fq='pre', count=1, panel=False, fill_paused=True)
? ? ? ? ? ??if?current_data.iloc[0,0] < ? ?current_data.iloc[0,1]:
? ? ? ? ? ? ? ? log.info("[%s]漲停打開,賣出"?% (stock))
? ? ? ? ? ? ? ? order_target_value(stock,?0)
? ? ? ? ? ? ? ? g.other_sale.append(stock)
? ? ? ? ? ? ? ? g.limitup_stocks.append(stock)
? ? ? ? ? ??else:
? ? ? ? ? ? ? ? log.info("[%s]漲停,繼續持有"?% (stock))
#1-5 如果昨天有股票賣出或者買入失敗造成空倉,剩余的金額當日買入
def?check_remain_amount(context):
? ? addstock_num =?len(g.other_sale)
? ? loss_num =?len(g.stoploss_list)
? ? empty_num = addstock_num + loss_num
? ? g.hold_list = context.portfolio.positions
? ??if?len(g.hold_list) < g.stock_num: ??
? ? ? ??# 計算需要買入的股票數量,止損倉位補足貨幣etf
? ? ? ??# 可替換下一行代碼以更換邏輯:改為將清空倉位全部補足股票,而非原作中止損倉位補充貨幣etf
? ? ? ??# num_stocks_to_buy = min(empty_num,g.stock_num-len(g.hold_list))
? ? ? ? num_stocks_to_buy =?min(addstock_num,g.stock_num-len(g.hold_list))
? ? ? ? target_list = [stock?for?stock?in?g.target_list?if?stock?not?in?g.limitup_stocks][:num_stocks_to_buy]
? ? ? ? log.info('有余額可用'+str(round((context.portfolio.cash),2))+'元。買入'+?str(target_list))
? ? ? ? buy_security(context,target_list,len(target_list))
? ? ? ??if?loss_num !=0:
? ? ? ? ? ? log.info('有余額可用'+str(round((context.portfolio.cash),2))+'元。買入貨幣基金'+?str(g.money_etf))
? ? ? ? ? ? buy_security(context,[g.money_etf],loss_num)
? ? g.stoploss_list = []
? ? g.other_sale ? ?= []
#1-6 下午檢查交易
def?trade_afternoon(context):
? ??if?g.trading_signal:
? ? ? ? check_limit_up(context)
? ? ? ? check_remain_amount(context)
? ? ? ? buy_security(context,[g.money_etf],1)
#1-7 止盈止損
def?stop_loss(context):
? ??if?g.run_stoploss:
? ? ? ? current_positions = context.portfolio.positions
? ? ? ??if?g.stoploss_strategy ==?1?or?g.stoploss_strategy ==?3:
? ? ? ? ? ??for?stock?in?current_positions.keys():
? ? ? ? ? ? ? ? price = current_positions[stock].price
? ? ? ? ? ? ? ? avg_cost = current_positions[stock].avg_cost
? ? ? ? ? ? ? ??# 個股盈利止盈
? ? ? ? ? ? ? ??if?price >= avg_cost *?2:
? ? ? ? ? ? ? ? ? ? order_target_value(stock,?0)
? ? ? ? ? ? ? ? ? ? log.debug("收益100%止盈,賣出{}".format(stock))
? ? ? ? ? ? ? ? ? ? g.other_sale.append(stock)
? ? ? ? ? ? ? ??# 個股止損
? ? ? ? ? ? ? ??elif?price < avg_cost * (1?- g.stoploss_limit):
? ? ? ? ? ? ? ? ? ? order_target_value(stock,?0)
? ? ? ? ? ? ? ? ? ? log.debug("收益止損,賣出{}".format(stock))
? ? ? ? ? ? ? ? ? ? g.stoploss_list.append(stock)
? ? ? ??if?g.stoploss_strategy ==?2?or?g.stoploss_strategy ==?3:
? ? ? ? ? ? stock_df = get_price(security=get_index_stocks('399101.XSHE')
? ? ? ? ? ? ? ? ? ? ? ? ,end_date=context.previous_date, frequency='daily'
? ? ? ? ? ? ? ? ? ? ? ? ,fields=['close',?'open'], count=1, panel=False)
? ? ? ? ? ??# 計算成分股平均漲跌,即指數漲跌幅
? ? ? ? ? ? down_ratio = (1?- stock_df['close'] / stock_df['open']).mean()
? ? ? ? ? ??# 市場大跌止損
? ? ? ? ? ??if?down_ratio >= g.stoploss_market:
? ? ? ? ? ? ? ? g.stoploss_list.append(stock)
? ? ? ? ? ? ? ? log.debug("大盤慘跌,平均降幅{:.2%}".format(down_ratio))
? ? ? ? ? ? ? ??for?stock?in?current_positions.keys():
? ? ? ? ? ? ? ? ? ? order_target_value(stock,?0)
#1-8 動態調倉代碼
def?adjust_stock_num(context):
? ? ma_para =?10??# 設置MA參數
? ? today = context.previous_date
? ? index_df = get_price('399101.XSHE', end_date=today,count = ma_para,fields =?'close', frequency='daily')
? ? ma = index_df['close'].mean()
? ? last_row = index_df['close'].iloc[-1]
? ? diff = last_row - ma
? ??# 根據差值結果返回數字
? ? result =?3?if?diff >=?500?else?\
? ? ? ? ? ? ?3?if?200?<= diff <?500?else?\
? ? ? ? ? ? ?4?if?-200?<= diff <?200?else?\
? ? ? ? ? ? ?5?if?-500?<= diff < -200?else?\
? ? ? ? ? ? ?6
? ??return?result
#2 過濾各種股票
def?filter_stocks(context, stock_list):
? ? current_data = get_current_data()
? ? ? ??# 漲跌停和最近價格的判斷
? ? last_prices = history(1, unit='1m', field='close', security_list=stock_list)
? ? ? ??# 過濾標準
? ? filtered_stocks = []
? ??for?stock?in?stock_list:
? ? ? ??if?current_data[stock].paused: ?# 停牌
? ? ? ? ? ??continue
? ? ? ??if?current_data[stock].is_st: ?# ST
? ? ? ? ? ??continue
? ? ? ??if?'退'?in?current_data[stock].name: ?# 退市
? ? ? ? ? ??continue
? ? ? ??if?stock.startswith('30')?or?stock.startswith('68')?or?stock.startswith('8')?or?stock.startswith('4'): ?# 市場類型
? ? ? ? ? ??continue
? ? ? ??if?not?(stock?in?context.portfolio.positions?or?last_prices[stock][-1] < current_data[stock].high_limit): ?# 漲停
? ? ? ? ? ??continue
? ? ? ??if?not?(stock?in?context.portfolio.positions?or?last_prices[stock][-1] > current_data[stock].low_limit): ?# 跌停
? ? ? ? ? ??continue
? ? ? ??# 次新股過濾
? ? ? ? start_date = get_security_info(stock).start_date
? ? ? ??if?context.previous_date - start_date < timedelta(days=375):
? ? ? ? ? ??continue
? ? ? ? filtered_stocks.append(stock)
? ??return?filtered_stocks
#2.1 篩選審計意見
def?filter_audit(context, code):
? ??# 獲取審計意見,近三年內如果有不合格(report_type為2、3、4、5)的審計意見則返回False,否則返回True
? ? lstd = context.previous_date
? ? last_year = lstd.replace(year=lstd.year -?3, month=1, day=1)
? ? q=query(finance.STK_AUDIT_OPINION.code, finance.STK_AUDIT_OPINION.report_type
? ? ? ? ? ).filter(finance.STK_AUDIT_OPINION.code==code,finance.STK_AUDIT_OPINION.pub_date>=last_year)
? ? df=finance.run_query(q)
? ? df['report_type'] = df['report_type'].astype(str)
? ? contains_nums = df['report_type'].str.contains(r'2|3|4|5')
? ??return?not?contains_nums.any()
#3-4 買入模塊
def?buy_security(context,target_list,num):
? ??#調倉買入
? ? position_count =?len(context.portfolio.positions)
? ? target_num = num
? ??if?target_num !=0:
? ? ? ? value = context.portfolio.cash / target_num
? ? ? ??for?stock?in?target_list:
? ? ? ? ? ? order_target_value(stock, value)
? ? ? ? ? ? log.info("買入[%s](%s元)"?% (stock,value))
? ? ? ? ? ??if?len(context.portfolio.positions) == g.stock_num:
? ? ? ? ? ? ? ??break
#4-1 判斷今天是否跳過月份
def?today_is_between(context):
? ??# 根據g.pass_month跳過指定月份
? ? month = context.current_dt.month
? ??# 判斷當前月份是否在指定月份范圍內
? ??if?month?in?g.pass_months:
? ? ? ? code =?'399303.XSHE'
? ? ? ? close = history(count =?3, unit='1d', field='close', security_list= [code], df =?False, skip_paused =?False, fq =?'none')[code]
? ? ? ??if?close[-1] > close[-2] *?0.995?and?close[-1] > close[-3] *?0.994:
? ? ? ? ? ??return?True
? ? ? ??# 判斷當前日期是否在指定日期范圍內
? ? ? ??return?False
? ??else:
? ? ? ??return?True
def?close_account(context):
? ??if?not?g.trading_signal:
? ? ? ? curr_data = get_current_data()
? ? ? ??if?len(g.hold_list) !=?0?and?g.hold_list != [g.money_etf]:
? ? ? ? ? ??for?stock?in?g.hold_list:
? ? ? ? ? ? ? ??if?stock == g.money_etf:
? ? ? ? ? ? ? ? ? ??continue
? ? ? ? ? ? ? ??if?curr_data[stock].last_price == curr_data[stock].low_limit?or?curr_data[stock].paused:
? ? ? ? ? ? ? ? ? ??continue
? ? ? ? ? ? ? ? order_target_value(stock,?0)
? ? ? ? ? ? ? ? log.info("賣出[%s]"?% (stock))
def?print_position_info(context):
? ??for?position?in?list(context.portfolio.positions.values()):
? ? ? ? securities=position.security
? ? ? ? cost=position.avg_cost
? ? ? ? price=position.price
? ? ? ? ret=100*(price/cost-1)
? ? ? ? value=position.value
? ? ? ? amount=position.total_amount ? ?
? ? ? ??print('代碼:{}'.format(securities))
? ? ? ??print('成本價:{}'.format(format(cost,'.2f')))
? ? ? ??print('現價:{}'.format(price))
? ? ? ??print('收益率:{}%'.format(format(ret,'.2f')))
? ? ? ??print('持倉(股):{}'.format(amount))
? ? ? ??print('市值:{}'.format(format(value,'.2f')))
? ??print('———————————————————————————————————————分割線————————————————————————————————————————')