QMT入门非常简洁的双均线策略4完结

前面我们分享了一段双均线策略的核心代码,并简单的完善了一下(QMT入门——非常简洁的双均线策略、QMT入门——非常简洁的双均线策略 2、QMT入门——非常简洁的双均线策略 3),今天做最后的完善:

1、由之前的固定的两支股池升级为5支股池,这5只股票来源于沪深300成份股,每天选择沪深300成份股中存货周转率最高的5支作为股池。由于存货周转率数据一般随财报公布,实际上股池每个季度更新一次。

2、获取行情函数,由get_history_data升级为get_market_data_ex,后者运行速度更快。

3、遇到股池更新时,将不在股池中的持仓股立即卖出,按新股池中的股票运行策略。

注意:这个策略不可用于实盘,只能用来跑回测。因为它太简陋了,就算用来模拟都不行,更不用说是实盘,举个例子来说,回测数据中,买入时间都是15:00:00,卖出时间都是00:00:00,这在实际中根本不可能。

更新后的代码如下:

#encoding:gbkimport numpy as npimport datetimeimport pandas as pd"""示例说明:双均线实盘策略,通过计算快慢双均线,在金叉时买入,死叉时做卖出"""class a():    passA = a() #创建空的类的实例 用来保存委托状态 def init(C):    A.acct= '666' #随便设置一个账号    A.acct_type= 'STOCK' #账号类型    A.amount = 10000 #单笔买入金额 触发买入信号后买入指定金额    A.line1=17   #快线周期    A.line2=27   #慢线周期    A.buy_code = 23 if A.acct_type == 'STOCK' else 33 #买卖代码 区分股票 与 两融账号    A.sell_code = 24 if A.acct_type == 'STOCK' else 34    print(f'双均线实盘示例{A.acct} {A.acct_type} 单笔买入金额{A.amount}')def handlebar(C):    #选股    A.stock = C.get_stock_list_in_sector('沪深300')    index = 0    df = pd.DataFrame(columns=['代码','存货周转率'])    for sto in A.stock:        inv_tur = C.get_financial_data('PERSHAREINDEX', 'inventory_turnover', sto[-2:], sto[:6], C.barpos)        index += 1        # 追加的新行数据        new_row = {'代码': sto, '存货周转率': inv_tur}        # 追加行        df.loc[len(df)] = new_row        df = df.sort_values(by=['存货周转率'], ascending=False)        A.stock = df['代码'][:5].tolist()    print('选出股票:',A.stock)    account = get_trade_detail_data(A.acct, A.acct_type, 'account')    if len(account)==0:        print(f'账号{A.acct} 未登录 请检查')        return    account = account[0]    available_cash = int(account.m_dAvailable)    #获取持仓数据,后续买入和卖出股票都要用到持仓数据    holdings = get_trade_detail_data(A.acct, A.acct_type, 'position')    holdings = {i.m_strInstrumentID + '.' + i.m_strExchangeID : i.m_nCanUseVolume for i in holdings}    #获取行情数据    data = C.get_market_data_ex(['close'],A.stock, end_time=timetag_to_datetime(C.get_bar_timetag(C.barpos),'%Y%m%d'),period = "1d",count = max(A.line1, A.line2)+1)    for hs in holdings:        if hs not in A.stock:            msg = f"{timetag_to_datetime(C.get_bar_timetag(C.barpos),'%Y%m%d')} 双均线实盘 换股"            passorder(A.sell_code, 1101, A.acct, hs, 14, -1, holdings[hs], '双均线实盘', 1 , msg, C)            print('换股!')    for s in  A.stock:        close_list = data[s]['close']        #行情数据不足将停止运行后面的代码        if len(close_list) < max(A.line1, A.line2)+1:            print('行情长度不足(新上市或最近有停牌) 跳过运行')            return    #以下四行在计算金叉死叉时要用到        pre_line1 = np.mean(close_list[-A.line1-1: -1])        pre_line2 = np.mean(close_list[-A.line2-1: -1])        current_line1 = np.mean(close_list[-A.line1:])        current_line2 = np.mean(close_list[-A.line2:])        #如果快线穿过慢线,则买入委托 当前无持仓 买入        vol = int(A.amount / close_list[-1] / 100) * 100 #买入数量 向下取整到100的整数倍        if A.amount < available_cash and vol >= 100 and s not in holdings and pre_line1 < pre_line2 and current_line1 > current_line2:            #下单开仓 ,参数说明可搜索PY交易函数 passorder            msg = f"{timetag_to_datetime(C.get_bar_timetag(C.barpos),'%Y%m%d')} 双均线实盘 {s} 上穿均线 买入 {vol}股"            passorder(A.buy_code, 1101, A.acct, s, 14, -1, vol, '双均线实盘', 1 , msg, C)            print(msg)        #如果快线下穿慢线,则卖出委托        if s in holdings and holdings[s] > 0 and pre_line1 > pre_line2 and current_line1 < current_line2:            msg = f"{timetag_to_datetime(C.get_bar_timetag(C.barpos),'%Y%m%d')} 双均线实盘 {s} 下穿均线 卖出 {holdings[s]}股"            passorder(A.sell_code, 1101, A.acct, s, 14, -1, holdings[s], '双均线实盘', 1 , msg, C)            print(msg)    #查询委托和成交情况    orders = get_trade_detail_data(A.acct, A.acct_type, 'order')    for o in orders:        avg_price = o.m_dTradeAmount/o.m_nVolumeTraded                bors = '买入' if o.m_nOffsetFlag==48 else '卖出'        print(f' 委托和成交情况:\n 股票代码: {o.m_strInstrumentID}.{o.m_strExchangeID},\n 买卖方向: {bors},\n 委托数量: {o.m_nVolumeTotalOriginal},\n'        f' 成交均价: {avg_price:.3f},\n 成交数量: {o.m_nVolumeTraded},\n 成交金额:{o.m_dTradeAmount:.2f}')            pos = get_trade_detail_data(A.acct, A.acct_type, 'position')    print(f'{timetag_to_datetime(C.get_bar_timetag(C.barpos),"%Y%m%d")}\n 持仓情况:')    mkv=0    if len(pos):                for p in pos:                    print(f' 股票代码:{p.m_strInstrumentID}.{p.m_strExchangeID},\n 剩余数量:{p.m_nVolume},\n 持仓成本:{p.m_dOpenPrice:.3f},\n 盈亏比例:{p.m_dProfitRate:.2%}')            mkv += p.m_dMarketValue    else:        print(' 空仓')    acco = get_trade_detail_data(A.acct, A.acct_type, 'account')#POSITION_STATISTICS  #position_statistics    for ac in acco:                print(f'{timetag_to_datetime(C.get_bar_timetag(C.barpos),"%Y%m%d")}\n 账户统计:')        print(f' 总资产:{ac.m_dBalance:.2f},\n 可用现金:{ac.m_dAvailable:.2f},\n 总市值:{mkv:.2f},\n 账户盈亏:{ac.m_dPositionProfit:.2%}')

返回(中段部分截图):

QMT入门非常简洁的双均线策略4完结

一些知识点讲解一下:

26行,返回沪深300指数成份股。

28行,创建只有列名的空dataframe。

29-36行,生成一个dataframe,有两列,分别为代码和存货周转率,按存货周转率降序排列。

38、39行,截取dataframe前5行,并转换为只有代码的列表。

51-55行,遇到股池更新时,将不在股池中的持仓股立即卖出。

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/73401
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 10 日
下一篇 2024 年 7 月 10 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注