Py学习  »  Python

含年化100%+的复合轮动因子,aitraderv4.7源码发布,支持duckdb列存访问数据(python源码+数据)

七年实现财富自由 • 1 年前 • 238 次点击  
原创内容第825篇,专注量化投资、个人成长与财富自由。
今天是周五,春天来了,桃花都开了。
周五是星球更新代码的日子,今天主要更新点如下:
1、duckdb loader按列加载多文件夹里的csv数据,性能更好。
2、解决了当天信号不显示的问题。
3、年化100%+的策略因子。
请前往星球下载:AI量化实验室——2025量化投资的星辰大海
代码随系统源码打包在策略集中:
核心代码片段如下:
from bt_algos_extend import TaskEngine


def ranking_ETFs():
    t = Task()
    t.name = '基于ETF历史评分的轮动策略'
    排序
    t.period = 'RunDaily'
    t.weight = 'WeighEqually'
    t.order_by_signal = 'trend_score(close,25)*0.4+(roc(close,5)+roc(close,10))*0.2+ma(volume,5)/ma(volume,20)'
    # t.start_date = '20180101'
    # t.end_date = '20240501'

    t.symbols = [
        '159915.SZ',  # '创业板ETF',
        '510180.SH',  # '上证180ETF',
        '518880.SH',  # '黄金ETF',
        '513100.SH',  # '纳指ETF',
        '159509.SZ',  # '纳指科技ETF',
        '512100.SH',  # '中证1000ETF',
        '513500.SH',  # '标普500ETF',
        '512480.SH',  # '科创100ETF'
    ]
    t.benchmark = '510300.SH'
    return t


res = Engine().run(ranking_ETFs())
import matplotlib.pyplot as plt

print(res.stats)
from matplotlib import rcParams

rcParams['font.family'] =  'SimHei'
# res.plot_weights()
res.prices.plot()
print(res.get_transactions())
df = (res.prices.pct_change() + 1).cumprod()
print(df.iloc[-1])
plt.show()
duckdb通过列的方式加载多个csv数据:
from datetime import datetime

import duckdb
import pandas as pd
from tqdm import tqdm


class DuckdbLoader:
    def __init__(selfpathsymbolscols=['close']start_date='20100101',
                 end_date=datetime.now().strftime('%Y%m%d')folder='/*'):
        self.path = path
        self.folder = folder
        self.start_date = start_date
        self.end_date = end_date
        self.cols = cols
        self.symbols = symbols
        self.df = None
        self._load_data(self.symbolsself.cols)

    def get_col_df(selfcol='close'):
        if col not in self.df.columns:
            print('列数据没有加载!')
            return None

        df_col = self.df[[col'symbol']].pivot_table(values=colindex=self.df.indexcolumns='symbol')
        return df_col

    def _load_data(selfsymbolscolumns):
        columns.extend(['symbol''date'])
        cols_str = ','.join(columns)

        symbols_str = None
        if symbols and len(symbols):
            symbols = ["'{}'".format(s) for in symbols]
            symbols_str = ",".join(symbols)

        query_str = """
    select {} from '{}{}/*.csv'
    where date >= '{}' and date <= '{}'
    """.format(cols_strself.pathself.folderself.start_dateself.end_date)
        if symbols_str:
            query_str += ' and symbol IN ({})'.format(symbols_str)

        df = duckdb.query(
            query_str
        ).df()
        df['date'] = df['date'].apply(lambda x: str(x))
        df.set_index('date'inplace=True)
        df.index = pd.to_datetime(df.index)
        df.sort_index(inplace=True, ascending=True)
        self.df = df

    def calc_all_expressions(selffieldsnames):
        df = self.df
        cols = []
        count = 0
        df.set_index([df.index'symbol']inplace=True)
        for fieldname in tqdm(zip(fieldsnames)):
            try:
                if len(field) <= 0:
                    continue
                se = calc_expr(dffield)

                count += 1
                if count 10:
                    df[name] = se
                else:
                    se.name = name
                    cols.append(se)
            except:
                print('{}错误'.format(field))
                import traceback
                print(traceback.print_exc())
                continue
        if len(cols):
            df_cols = pd.concat(colsaxis=1)
            df = pd.concat([dfdf_cols]axis=1)

        # df_all = df.loc[self.start_date: self.end_date].copy()
        # print(df_all.index.levels[0])
        df['symbol'] = df.index.droplevel(0)
        # df_all['symbol'] = df_all.index.levels[0]
        df.index = df.index.droplevel(1)
        self.df = df


if __name__ == '__main__':
    from config import DATA_ETF_QUOTES

    loader = DuckdbLoader(path=DATA_ETF_QUOTES.resolve()symbols=['510300.SH''159915.SZ'],
                          cols=['close''adj_factor'])
    df_col = loader.get_col_df('adj_factor')
    print(df_col)

     from datafeed.expr import calc_expr

    loader.calc_all_expressions(fields=['roc(close,20)']names=['roc_20'])
    df = loader.get_col_df('roc_20')
    print(df)

吾日三省吾身
宏观是我们必须承受的,而微观才是我们有所作为的。
回顾这二十年来,做对的事情有一些,有一点值得一提就是一直持续的做技术,当然不止于做技术。而且不是局限于工作中所需要的,而是觉得有意义,有外延和扩展性的。
用当下的话说,这叫“一人企业技术栈”。
当然花了很多心思,只不过是乐在其中,也并不觉得苦,也没有人要求去学习或做什么,而是就当成一个兴趣爱好。
从采集,到搜索再到推荐,再到后来的人工智能和量化投资。
做喜欢且擅长的事情,你并不会觉得是在工作或者加班。
我们讲"ABCZ"的计划,如果A(工作是你喜欢且擅长的),Z(投资计划,积累本金让自己财务小自由), 然后是造一个小商业系统(能够带来工资外,投资外的被动收入),当下以deepseek为代表的大模型及智能体,又进一步赋能“一个企业”技术栈。
日子是一天天过的,人生重要的转折点就那么几个。
在等待风来的日子里,做喜欢和擅长的事情,做到最好,开心点,就是这样!
代码和数据下载:AI量化实验室——2025量化投资的星辰大海

AI量化实验室 星球,已经运行三年多,1500+会员。

aitrader代码,因子表达式引擎、遗传算法(Deap)因子挖掘引等,支持vnpy,qlib,backtrader和bt引擎,内置多个年化30%+的策略,每周五迭代一次,代码和数据在星球全部开源。

扩展  •  历史文章   

EarnMore(赚得更多)基于RL的投资组合管理框架:一致的股票表示,可定制股票池管理。(附论文+代码)
deap系统重构,再新增一个新的因子,年化39.1%,卡玛提升至2.76(附python代码)

aitrader_v4.6代码发布,支持duckdb|股票全量数据(python代码+数据)

年化19.66%,回撤12%的稳健策略|manus的启发:基于大模型多智能体的智能投研系统(python代码+数据)

年化30.24%,最大回撤19%,综合动量多因子评分策略再升级(python代码+数据)

年化18%-39.3%的策略集 | backtrader通过xtquant连接qmt实战

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/180056