受欢迎的博客标签

通达信数据 - 使用通达信量化TQ(tdx quant)(3) - 量化脚本程序流程

Published

通达信数据 - 使用通达信量化TQ(tdx quant)(3) - 量化脚本程序流程

 

量化脚本程序流程

读取A股代码.txt 文件读取所有A股代码。
对每只股票进行分析计算
筛选出满足条件的股票
保存到c:\new_tdx_test\T0002\blocknew\LMSJ.blk

 

通达信TQ选股,调用通达信公式选股

import numpy as np
import pandas as pd
from tqcenter import tdxdata
import os
def ema(series, window):
    """计算指数移动平均"""
    return series.ewm(span=window, adjust=False).mean()
def sma(series, window, k=1):
    """计算简单移动平均"""
    return series.rolling(window=window).mean()
def llv(series, window):
    """计算周期内最低值"""
    return series.rolling(window=window).min()
def hhv(series, window):
    """计算周期内最高值"""
    return series.rolling(window=window).max()
def ma(series, window):
    """计算简单移动平均"""
    return series.rolling(window=window).mean()
def ref(series, periods):
    """引用若干周期前的数据"""
    return series.shift(periods)
def six_pulse_sword_signal(close, high, low):
    """
    计算六脉神剑选股信号
    返回值: True表示满足买入条件,False表示不满足
    """
    # MACD指标
    diff = ema(close, 8) - ema(close, 13)
    dea = ema(diff, 5)
    a1 = diff > dea
    
    # KDJ指标
    rsv1 = (close - llv(low, 8)) / (hhv(high, 8) - llv(low, 8)) * 100
    k = sma(rsv1, 3, 1)
    d = sma(k, 3, 1)
    a2 = k > d
    
    # RSI指标
    lc = ref(close, 1)
    rsi1 = sma(np.maximum(close - lc, 0), 5, 1) / sma(np.abs(close - lc), 5, 1) * 100
    rsi2 = sma(np.maximum(close - lc, 0), 13, 1) / sma(np.abs(close - lc), 13, 1) * 100
    a3 = rsi1 > rsi2
    
    # LWR指标
    rsv = -(hhv(high, 13) - close) / (hhv(high, 13) - llv(low, 13)) * 100
    lwr1 = sma(rsv, 3, 1)
    lwr2 = sma(lwr1, 3, 1)
    a4 = lwr1 > lwr2
    
    # BBI指标
    bbi = (ma(close, 3) + ma(close, 6) + ma(close, 12) + ma(close, 24)) / 4
    a5 = close > bbi
    
    # MTM指标
    mtm = close - ref(close, 1)
    mms = 100 * ema(ema(mtm, 5), 3) / ema(ema(np.abs(mtm), 5), 3)
    mmm = 100 * ema(ema(mtm, 13), 8) / ema(ema(np.abs(mtm), 13), 8)
    a6 = mms > mmm
    
    # 判断当前是否满足所有条件且前一天不满足
    current_condition = a1 & a2 & a3 & a4 & a5 & a6
    previous_condition = ref(current_condition, 1)
    
    # 涨买入信号:当前满足所有条件且前一天不满足
    buy_signal = current_condition & (previous_condition == False)
    
    # 返回最新的信号
    return buy_signal.iloc[-1] if len(buy_signal) > 0 else False
def save_to_block_file(selected_stocks, block_file_path):
    """
    将选股结果保存到通达信板块文件
    沪市: 1 + 6位代码
    深市: 0 + 6位代码
    北京: 2 + 6位代码
    """
    try:
        # 确保目录存在
        os.makedirs(os.path.dirname(block_file_path), exist_ok=True)
        
        # 打开文件准备写入(会清空原有内容)
        with open(block_file_path, 'w', encoding='gbk') as f:
            for stock in selected_stocks:
                # 解析股票代码
                if stock.endswith('.SH'):
                    # 沪市
                    code = '1' + stock[:6]
                elif stock.endswith('.SZ'):
                    # 深市
                    code = '0' + stock[:6]
                else:
                    # 默认处理(如果有北京市场或其他)
                    code = stock[:7]  # 保留原始格式的前7位
                
                f.write(code + '\n')
        
        print(f"选股结果已保存到 {block_file_path}")
        return True
    except Exception as e:
        print(f"保存选股结果到文件时出错: {e}")
        return False
def select_stocks_six_pulse_sword():
    """根据六脉神剑策略选股"""
    # 初始化连接
    tdxdata.initialize(__file__)
    
    try:
        # 从A股代码.txt文件中读取股票列表
        print("正在读取A股代码文件...")
        stock_list = []
        # 使用脚本所在目录的绝对路径来定位A股代码.txt文件
        script_dir = os.path.dirname(os.path.abspath(__file__))
        file_path = os.path.join(script_dir, 'A股代码.txt')
        print(f"尝试从路径读取文件: {file_path}")
        
        with open(file_path, 'r', encoding='utf-8') as f:
            for line in f:
                if '|' in line:
                    code, name = line.split('|')
                    name = name.strip()  # 去除换行符
                    
                    # 剔除ST和*ST股票
                    if name.startswith('ST') or name.startswith('*ST'):
                        continue
                    
                    # 转换代码格式以适配tdxdata接口
                    if code.startswith('SH'):
                        stock_code = code[2:] + '.SH'
                    elif code.startswith('SZ'):
                        stock_code = code[2:] + '.SZ'
                    else:
                        stock_code = code
                    stock_list.append(stock_code)
        
        print(f"共读取到{len(stock_list)}只A股股票")
        
        # 存储符合条件的股票
        selected_stocks = []
        
        # 对所有股票进行分析
        total_stocks = len(stock_list)
        print(f"\n开始分析全部{total_stocks}只股票...")
        
        for i, stock in enumerate(stock_list):
            try:
                # 获取最近60个交易日的日线数据(为了有足够的数据计算指标)
                data = tdxdata.get_market_data(
                    field_list=['Open', 'High', 'Low', 'Close'],
                    stock_list=[stock],
                    period='1d',
                    count=60,
                    dividend_type='none'
                )
                
                if not data or len(data) == 0:
                    continue
                
                # 转换为DataFrame
                df = pd.DataFrame({
                    'open': data['Open'][stock],
                    'high': data['High'][stock],
                    'low': data['Low'][stock],
                    'close': data['Close'][stock]
                })
                
                # 确保数据足够
                if len(df) < 30:
                    continue
                
                # 计算六脉神剑信号
                signal = six_pulse_sword_signal(df['close'], df['high'], df['low'])
                
                if signal:
                    selected_stocks.append(stock)
                
                # 显示进度(每500只股票显示一次)
                if (i + 1) % 500 == 0 or i == total_stocks - 1:
                    print(f"已处理{i + 1}/{total_stocks}只股票,已发现{len(selected_stocks)}只满足条件的股票...")
                    
            except Exception as e:
                # 忽略个别股票的错误
                print(f"处理股票{stock}时出错: {e}")
                continue
        
        print(f"选股完成,共选出{len(selected_stocks)}只符合条件的股票")
        return selected_stocks
        
    except FileNotFoundError as e:
        print(f"文件未找到: {e}")
        print("请确保A股代码.txt文件存在于脚本所在目录")
        return []
    except Exception as e:
        print(f"执行选股过程中发生错误: {e}")
        import traceback
        traceback.print_exc()
        return []
    finally:
        # 关闭连接
        try:
            tdxdata.close()
        except:
            pass
# 主程序入口
if __name__ == "__main__":
    print("开始执行六脉神剑选股策略...")
    # 打印当前工作目录
    import os
    print(f"当前工作目录: {os.getcwd()}")
    print(f"脚本所在目录: {os.path.dirname(os.path.abspath(__file__))}")
    
    try:
        selected = select_stocks_six_pulse_sword()
        if selected:
            print("\n符合六脉神剑买入条件的股票列表:")
            for stock in selected:
                print(stock)
                
            # 保存到通达信板块文件
            # 使用基于脚本位置的绝对路径
            script_dir = os.path.dirname(os.path.abspath(__file__))
            block_file_path = os.path.join(script_dir, "..", "..", "T0002", "blocknew", "LMSJ.blk")
            save_to_block_file(selected, block_file_path)
            
            # 输出选股结果供通达信使用
            result = "XG," + "|".join([f"{i}#{stock}" for i, stock in enumerate(selected)])
            print(f"\n选股结果代码: {result}")
        else:
            print("未发现符合条件的股票")
            print("XG,")
            
            # 即使没有选股结果,也创建空的板块文件
            # 使用基于脚本位置的绝对路径
            script_dir = os.path.dirname(os.path.abspath(__file__))
            block_file_path = os.path.join(script_dir, "..", "..", "T0002", "blocknew", "LMSJ.blk")
            save_to_block_file([], block_file_path)
    except Exception as e:
        print(f"程序执行过程中发生错误: {e}")
        import traceback
        traceback.print_exc()
        print("XG,")

source:wechat

通达信量化TQ支持的数据(股票和指数,K线数据,财务数据,交易数据)

支持调用通达信公式。

支持实盘交易