返回列表 发布新帖

python股票均线策略模板

5018 2
发表于 2024-1-4 16:08:51 | 显示全部楼层 阅读模式
本示例仅作策略演示和模板介绍,请不要直接用于实际交易


策略导入的方式
1. 直接复制到空代码文件
2. 将.rzrk附件导入到QMT/投研版内部

策略讲解


双均线策略是一种基于技术分析的交易策略,主要用于研判股票价格走势。该策略以两条不同周期的移动平均线(例如5日线与30日线,即短期均线和长期均线)的交叉情况作为买入或卖出信号。


以下是其中一些重要的专业概念:
移动平均线 (Moving Average, MA): 这是衡量股票在特定时间范围内平均价格的一种指标。它可以帮助投资者确定市场的趋势。
金叉: 当短期均线从下方穿过长期均线时,被称为“金叉”。这通常被视为一个买入信号,因为它可能预示着一个上涨趋势的开始。
死叉: 当短期均线从上方穿过长期均线时,被称为“死叉”。这通常被视为一个卖出信号,因为它可能预示着一个下跌趋势的开始。


尽管双均线策略在一些市场环境中能提供相对准确的交易信号,但它并非无懈可击。例如,在震荡市中,频繁发生的假信号可能导致不必要的交易和潜在损失。因此,投资者通常会配合其他技术分析工具(如相对强弱指标RSI、布林带等)或基本面信息来优化策略与决策。



回测结果
1704355604950.png

策略源码

  1. # coding:gbk

  2. # 单策略独立进程是指每个策略拥有自己独立的进程,策略之间互不影响
  3. # 在qmt内部使用单策略独立进程模式需要勾选上右侧的独立python进程
  4. # 也在外部IDE使用该模式,此时需要把bin.x64/Lib/site-packages/xtquant复制到自己的python环境变量下

  5. class _a():
  6.     pass

  7. A = _a()

  8. def init(C):
  9.    
  10.     A.symbol = "510050.SH" # 填一个具体合约
  11.     A.period = C.period
  12.     A.line1 = 20 # 第一根线的参数
  13.     A.line2 = 40 # 第二根线的参数
  14.     C.accID = "123123" # 回测时需要使用这一句
  15.     # C.accID = account # 实盘时需要使用这一句
  16.     C.main_stock= C.stockcode + '.' +C.market
  17.     return
  18.    
  19. def after_init(C):
  20.     # 不确定有没有数据的时候,下载一遍数据
  21.     if 1:
  22.         my_download([A.symbol,C.main_stock],period = A.period)

  23. def handlebar(C):
  24.     # print(C.barpos)
  25.     backTestTime = timetag_to_datetime(C.get_bar_timetag(C.barpos),"%Y%m%d%H%M%S")
  26.     print(backTestTime)
  27.     # 数据周期与右侧默认周期一致
  28.     kline = C.get_market_data_ex(['open', 'high','low','close'],[A.symbol],period = A.period, end_time = backTestTime,count = 3 + max([A.line1, A.line2]))[A.symbol]

  29.     ma1 = kline["close"].rolling(A.line1).mean()
  30.     ma2 = kline["close"].rolling(A.line2).mean()

  31.     holdings = get_stock_holdings(C.accID)
  32.     lots = holdings.get(A.symbol,{}).get("持仓数量",0)
  33.     avb_lots = holdings.get(A.symbol,{}).get("可用余额",0)
  34.     print(f"已走完K线 --- ma1:{ma1.iloc[-2]}  ma2:{ma2.iloc[-2]}" )
  35.     print(f"最新K线 --- ma2:{ma1.iloc[-1]}  ma2:{ma2.iloc[-1]}" )
  36.    
  37.     cross_up = (ma1.iloc[-2] > ma2.iloc[-2]) and (ma1.iloc[-3] < ma2.iloc[-3])
  38.     cross_down = (ma1.iloc[-2] < ma2.iloc[-2]) and (ma1.iloc[-3] > ma2.iloc[-3])
  39.    
  40.     # 如果有新的条件需要满足,可以在if语句用and进行连接
  41.    
  42.     if cross_up and lots == 0 :#
  43.         print(f"ma1上穿ma2")
  44.         my_passorder(C,A.symbol, "buy",10000)
  45.         
  46.     elif cross_down and avb_lots > 0:#
  47.         print(f"ma1下穿ma2")
  48.         my_passorder(C,A.symbol, "sell", lots)
  49.     else:
  50.         print(holdings)
  51.         
  52.         
  53.     return


  54. # --------------------股票版本------------------------------
  55. def my_passorder(C,stock,opentype,lots,price = None,m_strRemark = '系统备注'):
  56.     '''
  57.    
  58.     Args:
  59.         C: ContextInfo
  60.         stock: 股票代码
  61.         
  62.         opentype:
  63.                 'buy' 买股票
  64.                 'sell' 卖股票
  65.         lots: 股数
  66.         price: 下单价格,不指定时默认按对手价下单
  67.         m_strRemark = '系统备注' 用于自定义寻找orderID
  68.     '''
  69.     #holdings = get_holdings(C.accID,'stock')
  70.     opentype = opentype #买卖方向
  71.     op =1101  #股数
  72.     opType = 23 if opentype == 'buy' else 24# 若不为'sell' 则为buy
  73.     volumex = lots
  74.     price = 0 if not price else price # price参数必须存在
  75.     prType = 14 if not price else 11 # 若不指定价格,则默认按对手价下单
  76.     print(f'{stock} 新委托信息 方向{opentype} 价格{price} 量{volumex}')
  77.     #print(f"opType:{opType} , op:{op} , C.accID{C.accID} , stock{stock} , prType{prType} , price{price} , volumex{volumex}")
  78.     passorder(opType, op, C.accID,stock, prType, price, volumex,'交易注释',1,'{}'.format(m_strRemark), C)
  79.     print(f'委托发送完成')


  80. def get_stock_holdings(accid,symbol = None):
  81.     '''
  82.     Arg:
  83.         accondid:账户id
  84.         datatype:'FUTURE':期货,'STOCK':股票,......
  85.         symbol: 品种,不填默认返会全部持仓
  86.             
  87.     return:
  88.         {股票代码:{'手数':int,"持仓成本":float,'浮动盈亏':float,"可用余额":int}}
  89.     '''
  90.     PositionInfo_dict={}
  91.     resultlist = get_trade_detail_data(accid,"STOCK",'POSITION')
  92.     for obj in resultlist:
  93.         PositionInfo_dict[obj.m_strInstrumentID+"."+obj.m_strExchangeID] = {
  94.         "持仓数量":obj.m_nVolume,
  95.         "持仓成本":obj.m_dOpenPrice,
  96.         "浮动盈亏":obj.m_dFloatProfit,
  97.         "盈亏比例":obj.m_dProfitRate * 100,
  98.         "市值":obj.m_dMarketValue,
  99.         "可用余额":obj.m_nCanUseVolume,
  100.         "交易方向":obj.m_nDirection
  101.         }
  102.     if symbol:
  103.         return PositionInfo_dict[symbol]
  104.     else :
  105.         return PositionInfo_dict

  106. def my_download(stock_list,period,start_date = '', end_date = ''):
  107.     '''
  108.     用于显示下载进度
  109.     '''
  110.     if "d" in period:
  111.         period = "1d"
  112.     elif "m" in period:
  113.         if int(period[0]) < 5:
  114.             period = "1m"
  115.         else:
  116.             period = "5m"
  117.     elif "tick" == period:
  118.         pass
  119.     else:
  120.         raise KeyboardInterrupt("周期传入错误")


  121.     n = 1
  122.     num = len(stock_list)
  123.     for i in stock_list:
  124.         print(f"当前正在下载{n}/{num}")
  125.         
  126.         download_history_data(i,period,start_date, end_date)
  127.         n += 1
  128.     print("下载任务结束")

复制代码


策略附件

PYTHON回测_实盘示例.rzrk (11.54 KB, 下载次数: 131)

评论2

心如止水
发表于 2024-3-29 11:19:13 | 显示全部楼层
还有其他想学习的 QMT 小技巧吗?欢迎大家在下方留言,版主将根据大家的留言持续更新哦!
AA缠
发表于 2024-9-9 22:40:00 | 显示全部楼层
怎么能获得双均线死叉后到金叉前之间所有k线的最低点价格?
客服专线

400-080-8112

用思考的速度交易,用真诚的态度合作,我们是认真的!
  • 关注公众号
  • 添加微信客服
Copyright © 2001-2025 迅投QMT社区 版权所有 All Rights Reserved. 蜀ICP备19002686号-2
关灯
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表