如何通过executor.map从Tradermade获取时间序列数据并传递kwarg参数
解决ThreadPoolExecutor.map无法传递固定关键字参数的方案
你可以通过functools.partial预先绑定tm.timeseries的固定参数,或者自定义包装函数封装请求逻辑,即可兼容executor.map的迭代调用逻辑,优化后的并发拉取代码如下:
from concurrent.futures import ThreadPoolExecutor from functools import partial # 交易品种列表 symbols = [ 'AUDUSD', 'EURUSD', 'GBPUSD', 'USDCAD', 'USDJPY', 'USDCHF', 'AUDCAD', 'AUDCHF', 'AUDJPY', 'AUDNZD', 'CADCHF', 'CADJPY', 'CHFJPY', 'EURAUD', 'EURCHF', 'EURCAD', 'EURGBP', 'EURJPY', 'EURNZD', 'EURZAR', 'GBPAUD', 'GBPCAD', 'GBPCHF', 'GBPJPY', 'GBPNZD', 'NZDCAD', 'NZDCHF', 'NZDJPY', 'NZDUSD', 'USDMXN', 'USDNOK', 'USDSEK', 'USDSGD', 'USDTRY', 'USDZAR' ] rates = {} # 预先绑定tm.timeseries的通用固定参数,仅留currency作为动态入参 fetch_timeseries = partial( tm.timeseries, start=from_date, end=to_datetime, interval="hourly", fields=["open", "high", "low", "close"] ) def process_single_symbol(symbol): # 封装单交易品种的完整处理逻辑,每个线程独立执行 point = 3 if "JPY" in symbol else 5 ts_data = fetch_timeseries(currency=symbol) return symbol, Rates(symbol, point, ts_data) if __name__ == "__main__": # 线程池max_workers可根据接口请求频率限制调整,IO密集型任务一般设为10~20即可 with ThreadPoolExecutor(max_workers=16) as executor: # executor.map自动迭代symbols列表,分配给空闲线程执行,返回结果和输入顺序一致 for symbol, rate_obj in executor.map(process_single_symbol, symbols): rates[symbol] = rate_obj
核心逻辑说明
functools.partial的作用是把函数的部分参数预先固定,返回一个新的可调用对象,这里我们把所有交易品种通用的时间范围、时间粒度、返回字段都提前绑定,调用时只需要传入动态的currency参数即可,不需要再重复传固定参数。- 自定义的
process_single_symbol函数封装了单交易品种的完整处理逻辑:计算精度、拉取数据、生成Rates实例,返回的元组方便后续直接存入结果字典。 - 并发执行会把多个请求的IO等待时间重叠,原来66秒的同步耗时通常可以降到几秒内。
如果不想引入functools.partial依赖,也可以直接在process_single_symbol函数内直接写死tm.timeseries的固定参数,运行效果完全一致。
内容的提问来源于stack exchange,提问作者JessicaRyan
相关产品推荐
相关产品推荐

