【量化】使用wind获取商品期货全品种全合约日K

今天爬一下商品期货的全品种全合约,大部分人只会用品种的主力连续,但因为我们需要前收盘价以便复权,所以需要全部合约,因此遇到的第一个问题是如何获取全部合约的代码,这个问题也涵盖着如何获取当期正在交易的合约代码。

其次因为我需要的是最新数据,而历史数据是有其他人给的,所以需要对上历史数据的口径。

大致思路就是:

  1. 设置基础信息(可以在过程中不断完善);
  2. 获取全部期货合约代码;
  3. 根据前面得到的代码获取日线数据;
  4. 存储数据。

获取全部合约代码

这个最开始想着确实不知道怎么办,因为数据源是wind,就去客户群里问有没有这个函数,得到答案有,于是正常写代码获取:

contract_code = w.wset("sectorconstituent", date=today_date, sectorid=1000015512000000)
contract_code = pd.DataFrame(contract_code.Data, index=contract_code.Fields).T
print(contract_code)
contract_code.to_csv(base_path + '\code.csv', encoding='gbk')

这个contract_code打印出来是这样的。

          date   wind_code sec_name
0   2023-11-23   A2401.DCE   豆一2401
1   2023-11-23   A2403.DCE   豆一2403
2   2023-11-23   A2405.DCE   豆一2405
3   2023-11-23   A2407.DCE   豆一2407
4   2023-11-23   A2409.DCE   豆一2409
..         ...         ...      ...
723 2023-11-23  ZN2407.SHF   沪锌2407
724 2023-11-23  ZN2408.SHF   沪锌2408
725 2023-11-23  ZN2409.SHF   沪锌2409
726 2023-11-23  ZN2410.SHF   沪锌2410
727 2023-11-23  ZN2411.SHF   沪锌2411

这里用到了一个today_date, 后面爬日K时也是需要时间范围的,所以前面就可以设置好:

today_date = datetime.now()  # 设置今天的日期
ten_days_before = today_date - timedelta(days=10)  # 从今天减去10天得到新的日期
end_time = today_date.strftime('%Y-%m-%d')
start_time = ten_days_before.strftime('%Y-%m-%d')

获取日线数据

因为源数据的文件名就是上述的sec_name.csv,所以我们要用到这个,而wind_code则是获取日K数据需要的代码。

所以整体思路是这样的:

for index, row in contract_code.iterrows():
    wind_code = row['wind_code']
    sec_name = row['sec_name']
    print(sec_name)
    # ==== 爬取日度K线数据
    daily_k_data = get_day_K_function(wind_code, start_time, end_time)

def get_day_K_function(code, time_start, time_end):
    data = w.wsd(code,
                 "pre_close,open,high,low,close,chg,pct_chg,volume,amt,pre_settle,settle,oi,oi_chg,sccode,trade_hiscode",
                 time_start, time_end, unit=1)
    data = pd.DataFrame(data.Data, index=data.Fields, columns=data.Times).T
    data.reset_index(inplace=True)
    data.rename(columns={'index': '交易日期'}, inplace=True)
    data.rename(columns={
        'PRE_CLOSE': '前收盘价',
        'OPEN': '开盘价',
        'HIGH': '最高价',
        'LOW': '最低价',
        'CLOSE': '收盘价',
        'CHG': '涨跌',
        'PCT_CHG': '涨跌幅',
        'VOLUME': '成交量',
        'AMT': '成交额',
        'PRE_SETTLE': '前结算价',
        'SETTLE': '结算价',
        'OI': '持仓量',
        'OI_CHG': '持仓变动',
        'TRADE_HISCODE': '合约代码'
    }, inplace=True)
    data['成交额'] = data['成交额'] / 10000
    return data

储存数据

储存数据由于自己这里的特殊性,所以做的相对复杂些,我这里的原始路径是’base_path/sec_name前面的文字/sec_name’,所以首先要提取里面的文字部分:

def extract_chinese_name(sec_name):
    # 使用正则表达式匹配所有非数字字符直到字符串结束
    match = re.match(r'^(.*?)(\d+)$', sec_name)
    if match:
        # 返回匹配的中文部分
        return match.group(1)
    else:
        # 如果没有匹配到数字,则说明整个字符串都是名称
        return sec_name

路径分成两种情况,一种是已经有的合约和商品,这里发现存在以后直接读取、合并、储存即可;另一种是新上市的合约和商品,那就直接用新数据。

我这里会把第一行添加一道文本,所以略微复杂了些:

base_path = 'D:\data\\future\day_k'
explanation_text = "私人整理,请勿传播"  # 第一行放的文本
for index, row in contract_code.iterrows():
    ······
    ······
    # ==== 路径
    # 创建子目录路径
    sub_directory = os.path.join(base_path, extract_chinese_name(sec_name))
    if not os.path.exists(sub_directory):
        os.makedirs(sub_directory)  # 如果子目录不存在就创建一个
    file_path = os.path.join(sub_directory, f"{sec_name}.csv")

    # ==== 存储
    if os.path.exists(file_path):
        # 文件已存在,读取原始数据并与新数据合并
        historical_data = pd.read_csv(file_path, skiprows=1, parse_dates=['交易日期'], encoding='gbk')
        historical_data['交易日期'] = pd.to_datetime(historical_data['交易日期'])
        daily_k_data['交易日期'] = pd.to_datetime(daily_k_data['交易日期'])

        # 合并旧数据和新数据
        combined_data = pd.concat([historical_data, daily_k_data]).drop_duplicates(['交易日期'])

        # 再排序一次
        combined_data.sort_values('交易日期', inplace=True)

        # 保存或覆盖CSV文件
        file_title = pd.DataFrame(columns=[explanation_text])
        file_title.to_csv(file_path, index=False, encoding='GBK', mode='w')
        combined_data.to_csv(file_path, index=False, mode='a', encoding='GBK')
    else:
        # 文件不存在,直接使用新数据
        combined_data = daily_k_data
        combined_data.sort_values('交易日期', inplace=True)
        combined_data.drop_duplicates(subset=['交易日期'], inplace=True) # 任何数据都去重排序,以防万一
        # 将说明文本和数据写入文件
        with open(file_path, 'a', encoding='gbk') as f:
            f.write(explanation_text + '\n')  # 写入说明文本并换行
            combined_data.to_csv(f, index=False, encoding='gbk')
  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值