【聚宽】JoinQuant 技术分析库 jqlib.technical_analysis 使用教程

JoinQuant 内置技术分析库 jqlib.technical_analysis 实战指南

无需手动计算复杂的指标,利用 JoinQuant 的 jqlib.technical_analysis 库快速实现技术分析策略。本教程将以 GDX 济安线为例,展示如何调用库中函数并将其整合到交易策略中。

Q: 我该如何计算一个股票的济安线(GDX)指标?

在聚宽(JoinQuant)平台上,计算股票的济安线(GDX)指标最直接且高效的方法是使用平台提供的 jqlib 技术分析库。该库内置了 GDX 函数,可以直接返回济安线、压力线和支撑线的数据。

以下是具体的计算方法和代码示例。

1. 使用 jqlib 库计算 GDX(推荐)

聚宽的 jqlib.technical_analysis 模块封装了 GDX 指标的计算逻辑,无需手动编写复杂的公式。

函数说明:
GDX(security_list, check_date, N=30, M=9)

  • security_list: 股票代码列表(如 ['000001.XSHE'])。
  • check_date: 计算指标的日期(如 '2023-01-01')。
  • N: 统计天数,默认 30。
  • M: 偏离度参数,默认 9。

返回值:
返回三个字典(dict),分别代表:

  1. 济安线 (JAX)
  2. 压力线 (YLX)
  3. 支撑线 (ZCX)
代码示例
# -*- coding: utf-8 -*-
from jqlib.technical_analysis import *

def initialize(context):
    # 设定要查询的股票
    security = '000001.XSHE'
    
    # 获取当前日期的 GDX 指标数据
    # 注意:在回测中 context.current_dt 是当前时间
    # N=30, M=9 是常见默认参数
    jax, ylx, zcx = GDX([security], check_date=context.current_dt, N=30, M=9)
    
    # 获取具体数值
    current_jax = jax[security]  # 济安线
    current_ylx = ylx[security]  # 压力线
    current_zcx = zcx[security]  # 支撑线
    
    # 打印结果
    print("股票: %s" % security)
    print("济安线: %f" % current_jax)
    print("压力线: %f" % current_ylx)
    print("支撑线: %f" % current_zcx)

    # 简单的策略逻辑示例:
    # 如果收盘价突破压力线,可能视为强势信号(仅作示例,非投资建议)
    current_price = data[security].close
    if current_price > current_ylx:
        print("价格突破压力线,可能存在上涨趋势")

2. GDX 指标的计算原理

如果您需要了解其背后的逻辑,或者需要手动复现,GDX 的计算公式如下:

  1. 计算加权价格与均线的偏离度 (AA)
    A A = ∣ ( 2 × C + H + L ) / 4 − M A ( C , N ) ∣ M A ( C , N ) AA = \frac{|(2 \times C + H + L) / 4 - MA(C, N)|}{MA(C, N)} AA=MA(C,N)(2×C+H+L)/4MA(C,N)
    其中:C=收盘价, H=最高价, L=最低价, MA=简单移动平均

  2. 计算济安线 (JAX)
    J A X = D M A ( C , A A ) JAX = DMA(C, AA) JAX=DMA(C,AA)
    DMA 为动态移动平均,即以 AA 为权重对收盘价进行动态平滑。

  3. 计算压力线与支撑线

    • 压力线 = ( 1 + M / 100 ) × J A X (1 + M / 100) \times JAX (1+M/100)×JAX
    • 支撑线 = ( 1 − M / 100 ) × J A X (1 - M / 100) \times JAX (1M/100)×JAX

3. 注意事项

  1. 引入库:必须在代码开头使用 from jqlib.technical_analysis import *
  2. 数据类型GDX 函数返回的是字典,键为股票代码,值为指标数值。即使只查询一只股票,也需要通过 [security] 索引来获取数值。
  3. NaN值处理:如果股票上市时间不足 N 天,或者数据不足,计算结果可能返回 NaN,在策略中应当对这种情况进行过滤。

Q&A

Q: GDX 指标中的 N 和 M 参数通常如何设置?
A: 默认参数通常为 N=30 和 M=9。N 代表计算移动平均和偏离度的周期,M 代表压力线和支撑线相对于济安线的上下偏离百分比。您可以根据策略对灵敏度的需求调整这些参数。

Q: 可以在研究环境(Notebook)中使用这个函数吗?
A: 可以。在研究环境中,只需确保引入了 from jqlib.technical_analysis import *,并将 check_date 设置为您想要查询的具体历史日期即可。

Q: GDX 指标的主要用途是什么?
A: GDX 是一种路径型指标。济安线本身可以看作是一种特殊的均线,用于判断趋势方向;压力线和支撑线则构成了价格波动的通道。通常用于捕捉趋势启动或判断价格是否处于超买/超卖区域。


不会写量化代码?欢迎来 EasyQuant 体验 AI 编写量化策略: EasyQuant

# 导入函数 from jqdata import * from jqlib.technical_analysis import * # 初始化函数,设定基准等等 def initialize(context): # 设定沪深300作为基准 set_benchmark('000300.XSHG') # 开启动态复权模式(真实价格) set_option('use_real_price', True) # 输出内容到日志 log.info() log.info('初始函数开始运行且全局只运行一次') # 过滤掉order系列API产生的比error级别低的log log.set_level('order', 'error') ### 股票相关设定 ### # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock') g.stocks = [] g.trade_price = {} g.highest_price = {} g.trade_stock = 0 g.loss_stop = 0.05 g.profit_stop = 0.1 ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的) # 开盘前运行 run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') # 开盘时运行 run_daily(market_open, time='open', reference_security='000300.XSHG') # 收盘后运行 run_daily(after_market_close, time='after_close', reference_security='000300.XSHG') def check_stocks(stocks,date, pre_date, current_data): open = [] close= [] ma = MA(stocks, check_date=date, timeperiod=120, unit='1d') K, D, J = KDJ(stocks, check_date=date, N=9, M1=3, M2=3, unit='1d') pre_K, pre_D, pre_J = KDJ(stocks, check_date=pre_date, N=9, M1=3, M2=3, unit='1d') for stock in stocks: if current_data[stock].paused: continue current_price = current_data[stock].last_price ma_open = current_price>=ma KDJ_open = pre_K<pre_D and K>D ma_close = current_price<ma KDJ_close = pre_K>pre_D and K<D if ma_open and KDJ_open: open.append(stock) if ma_close or KDJ_close: close.append(stock) return open,close def before_market_open(context): q = query( indicator.code ).filter( indicator.roa>0.15, valuation.pb_ratio<0.98, cash_flow.subtotal_operate_cash_inflow>1000000, income.net_profit>1000000 ) g.stocks=get_fundamentals(q, date=context.current_dt)['code'].tolist() log.info(len(g.stocks)) def market_open(context): date = context.current_dt pre_date = context.previous_date current_data = get_current_data() log.info(g.loss_stop) log.info(g.stocks) Traceback (most recent call last): File "/tmp/jqcore/jqboson/jqboson/core/entry.py", line 337, in _run engine.start() File "/tmp/jqcore/jqboson/jqboson/core/engine.py", line 249, in start self._dispatcher.start() File "/tmp/jqcore/jqboson/jqboson/core/dispatcher.py", line 280, in start self._run_loop() File "/tmp/jqcore/jqboson/jqboson/core/dispatcher.py", line 240, in _run_loop self._loop.run() File "/tmp/jqcore/jqboson/jqboson/core/loop/loop.py", line 118, in run self._handle_queue() File "/tmp/jqcore/jqboson/jqboson/core/loop/loop.py", line 164, in _handle_queue message.callback(**message.callback_data) File "/tmp/jqcore/jqboson/jqboson/core/dispatcher.py", line 110, in callback self._event_bus.emit(evt) File "/tmp/jqcore/jqboson/jqboson/core/bus.py", line 47, in emit ret.append(call(event)) File "/tmp/jqcore/jqboson/jqboson/core/strategy.py", line 433, in _wrapper return cb(self._context.strategy_environment.strategy_context, **cb_kwargs) File "/tmp/strategy/user_code.py", line 69, in market_open log.info(g.loss_stop) UnboundLocalError: local variable 'g' referenced before assignment
最新发布
12-13
# 导入函数 from jqdata import * from jqlib.technical_analysis import * from datetime import * import time from decimal import Decimal from MyTT import * import requests import json import talib # 引入TA-Lib,用于技术分析 ## 初始化函数,设定基准等等 def initialize(context): #参数 get_canshu(context) # 设定上证指数作为基准 #'000300.XSHG' set_benchmark("000852.XSHG" ) # 开启动态复权模式(真实价格) set_option('use_real_price', True) set_option("avoid_future_data", True) log.info('初始函数开始运行且全局只运行一次') log.set_level('order', 'error') ### 期货相关设定 ### # 设定账户为金融账户 set_subportfolios([SubPortfolioConfig(cash=context.portfolio.starting_cash, type='index_futures')]) # 期货类每笔交易时的手续费是:买入时万分之0.23,卖出时万分之0.23,平今仓为万分之23 set_order_cost(OrderCost(open_commission=0.000023, close_commission=0.000023,close_today_commission=0.000023), type='index_futures') # 设定保证金比例 set_option('futures_margin_rate', 0.15) # 设置期货交易的滑点 set_slippage(StepRelatedSlippage(2)) # 开盘运行 run_daily( before_market_open, time='09:30', reference_security=g.reference) # 盘中每分钟运行一次 run_daily(market_open, time='every_bar', reference_security=g.reference) def get_canshu(context): g.unit='1m' #数据运行周期 g.flag = True #开平仓标记 # g.reference = "IM9999.CCFX" #分析参考标的 g.reference = "000852.XSHG" #分析参考标的 g.zft1 = False g.long_short = 'long' g.counts = 0 g.loss_s = 6000 g.gaokai = True ## 开盘前运行函数 def before_market_open(context): g.IM_current_month = get_future_contracts('IM')[0] # 获取下月沪深300指数期货合约 g.IM_next_month = get_future_contracts('IM')[1] g.counts = 0 current_time2 = context.current_dt # 获取当月合约交割日期 end_data = get_CCFX_end_date(g.IM_current_month) #如果当日是交割日,并且没有平仓,那么先平仓,后开次月仓 if context.current_dt.date() == end_data: g.IM_current_month = g.IM_next_month df2 = get_price(g.IM_current_month,count=241,end_date=current_time2, frequency=g.unit, fields=['close','high','low','open'], skip_paused=False, fq='pre') #df2.close.values[-1] g.highest_high = 0 log.info('最高级价格:') log.info(g.highest_high) ## 开盘时运行函数 def market_open(context): #当前运行时间 current_time = context.current_dt IM_current_month = g.IM_current_month #下月合约 IM_next_month = g.IM_next_month #log.info(IM_current_month) # 分析- 沪深300指数 reference = g.reference if '0930' < current_time.strftime("%H%M") < '1454': #datas = get_bars(g.reference, count=120, unit='1m', fields=['close', 'high', 'low'], include_now=False, df=True) df = get_price(g.IM_current_month,count=241,end_date=current_time, frequency=g.unit, fields=['close','high','low','open'], skip_paused=False, fq='pre') close = df.close.values high = df.high.values low = df.low.values open = df.open.values ma45 = MA(close,45) ema9 = EMA(close,9) ema21 = EMA(close,21) sma5 = SMA(close,5) sma20 = SMA(close,20) #rsi1 = RSI(close,6) rsi1 = talib.RSI(close, 7) # 计算RSI指标,周期为10 MTR = MAX(MAX((high-low),ABS(REF(close,1)-high)),ABS(REF(close,1)-low)) ATR14 = MA(MTR,14) ATR10 = MA(MTR,10) # ATR14 = talib.ATR(high, low, close, timeperiod=14) # ATR10 = talib.ATR(high, low, close, timeperiod=10) # RSV = (close-LLV(low,9))/(HHV(high,9)-LLV(low,9))*100; # kdj_k,kdl_d,kdj_j = KDJ(close, high, low, N=9,M1=3,M2=3) # dif,dea,macd = MACD(close, 12,26,9) log.info('目前价格:'+str(close[-1])) current_price = close[-1] # log.info("k线") # log.info(open[-1], high[-1], low[-1], close[-1]) if np.isnan(rsi1[-1]): # 处理NaN值 rsi1[-1] = 50 # 横盘时设为中性值 log.info("rsi是空") if g.counts<=5 and g.flag and rsi1[-1]>65 and ATR14[-1] > ATR10[-1]: orders = order(IM_current_month, 1, side=g.long_short) g.counts += 1 g.flag = False g.highest_high = close[-1] # 开仓时初始化最高点为当前价格 log.info('买入价格:'+str(close[-1])) #g.stop_loss_price = close[-1] - 2 * ATR14[-1] # 2倍ATR作为止损幅度 if not g.flag: if current_price > g.highest_high: g.highest_high = close[-1] #计算回落 drop_ratio = (g.highest_high - current_price )/ g.highest_high # 判断是否达到止损条件 #if drop_ratio >= 0.004: if rsi1[-1]<25 and (ATR14[-1] >3 and ATR10[-1]>3): #if rsi1[-1]>65: log.info(ATR14[-1],ATR10[-1]) # 卖平 orders = order_target(IM_current_month, 0, side=g.long_short) log.info('最高级价格:'+str(g.highest_high)) log.info('卖出价格:'+str(close[-1])) log.info(current_price) g.flag = True if current_time.strftime("%H%M") == '1454' and g.counts == 0 and g.flag: current_data = get_current_data() high_limit = current_data[IM_current_month].high_limit last_price = current_data[IM_current_month].last_price low_limit = current_data[IM_current_month].low_limit if last_price != high_limit and last_price != low_limit: orders = order(IM_current_month, 1, side=g.long_short) # results = interface(current_time,IM_current_month,g.name,"开多",orders.price,g.strategy_id) # results_print(results) g.flag = False print('今日开仓次数不足1需下单') if current_time.strftime("%H%M") >= '1455': if not g.flag: current_data = get_current_data() high_limit = current_data[IM_current_month].high_limit last_price = current_data[IM_current_month].last_price low_limit = current_data[IM_current_month].low_limit if last_price != high_limit and last_price != low_limit: orders = order_target(IM_current_month, 0, side=g.long_short) g.flag = True log.info("===1455日内平仓===") ########################## 获取期货合约信息,请保留 ################################# # 获取金融期货合约到期日 def get_CCFX_end_date(future_code): # 获取金融期货合约到期日 return get_security_info(future_code).end_date这是我的交易代码在这上面优化
07-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值