QMT入门非常简洁的双均线策略3

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

1、将交易的股票数量增加至多只(本次以2支演示)。

2、增加了每日的持仓情况。

3、增加了每日的账户情况。

更新后的代码如下:

#encoding:gbk
import numpy as np
import datetime


"""
示例说明:双均线实盘策略,通过计算快慢双均线,在金叉时买入,死叉时做卖出
"""


class a():
    pass
A = a() #创建空的类的实例 用来保存委托状态 


def init(C):
    A.stock= ['000002.SZ','002049.SZ'] #交易品种
    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
    #设置股票池 订阅品种行情
    C.set_universe(A.stock)
    print(f'双均线实盘示例{A.stock} {A.acct} {A.acct_type} 单笔买入金额{A.amount}')


def handlebar(C):
    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_history_data(max(A.line1, A.line2)+1, '1d', 'close',dividend_type='none')
    for s in  A.stock:
        close_list = data[s]
    #行情数据不足将停止运行后面的代码
        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')
        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入门非常简洁的双均线策略3

现在每个回测的交易日都有持仓情况和账户统计,如发生交易,会显示委托和成交情况。

一些知识点讲解一下:

第14行,多只股票用列表、元组或集合的形式赋值都可以,回测都能正常运行。

第38行,用for循环实现对第14行的每一只股票进行判断和交易。

第69行,用get_trade_detail_data(A.acct, A.acct_type, ‘position’)函数来获取整体持仓情况。

第71、76行,用来计算账户总市值。我用get_trade_detail_data(A.acct, A.acct_type, ‘account’)取出来的总市值总是0,不知道是什么原因,于是,只好用最原始的方式——将每只股票的市值求和。

第74行,用for循环来提取每一支股票的持仓情况。

第79行,用get_trade_detail_data(A.acct, A.acct_type, ‘account’)函数来获取账户情况。

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

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

相关推荐

发表回复

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