Skip to content

1、快速入门

woldy edited this page Dec 26, 2023 · 1 revision

一、所需环境

  • Ubuntu系统(其它Linux理论上可行,但是我没有试,Windows可能会有部分功能异常)
  • Python3.9(更高版本理论上可行)
  • Mysql(用于存储采集到的初始数据)
  • Redis(缓存)
  • 500G硬盘,4核16G或以上配置

二、环境准备

2.1、Conda

虽然理论上只需要有python环境即可,但是根据经验,使用Conda单独为项目创建一个独立的环境是必要的,

本文档并不会单独介绍Conda的安装,具体的安装步骤请参考Anaconda官网

如果您是一个纯新手,对于Anaconda、Conda和Pip的区别,可自行查阅互联网或咨询ChatGPT,

本文档假设您已安装并配置好了Conda环境,使用如下命令重建并切换到finhack的独立python环境:

conda remove --name finhack --all
conda create --name finhack python=3.9
conda activate finhack
image

此时您在命令行前部分的conda环境标识应为finhack。

2.2、Mysql & Redis

本项目在初始采集数据时、以及后期模型训练、交易回测的管理,都会用到mysql数据库,一些缓存会用到redis数据库

虽然本项目支持纯文件形式的缓存,但还是建议安装redis,项目后期有可能会加强对redis的依赖,

如果您的计算机中已经安装了mysql以及redis,又或者您知道这两个软件如何安装且希望自己安装,那么可以跳过,并自行导入database目录中的sql文件,

如果您嫌麻烦,或之前并未使用过mysql或redis这类数据库,可以安装Docker后,运行项目中的 script/docker.sh 进行自动创建,

image

该命令会自动在当前目录下创建database/mysql-data目录和database/redis-data目录,并自动导入database目录中的sql文件

image

调用脚本后安装到docker中的mysql端口映射到本机为3307、redis映射到本机端口为6380,密码均为finhack,使用如下命令连接mysql

docker exec -ti finhack-mysql mysql -uroot -pfinhack 
image

2.3、finhack

做好如上准备后,则可以继续安装finhack包,安装finhack包有两种方式,一种是直接通过pip源安装:

pip install finhack

另一种是在项目中,通过如下命令安装

pip install .
image

三、项目配置

3.1、创建项目

finhack project create --project_path=./test_project
image

3.2、切换路径

框架所有命令,都需要在项目当前的文件夹下执行(其实也支持参数指定项目目录)

所以我们先cd到test_project下:

image

3.3、配置文件

配置文件的路径为 data/config/*.conf

image

快速体验项目,我们只需要先修改两个配置文件,一个是data/config/db.conf,把数据库端口、密码填上,只填写tushare、finhack两个库和redis即可

记得修改端口!!!

image

另一个文件是data/config/ts.conf,这里主要是填写tushare的token,这个是数据采集用

image

四、快速体验(A股)

4.1、数据采集

配置好数据库以及tushare的token后,可以使用如下命令开启数据采集,该命令将自动获取tushare的数据,并保存到mysql中:

finhack collector run --vendor=tushare
image

如果你希望后台运行,可以增加 --background参数,任务将在后台运行,日志会保存到 data/logs/collector.log 中

finhack collector run --vendor=tushare --background
image
tail -f data/logs/collector.log 
image

如果您想停止后台任务,则可以使用如下命令:

finhack collector stop --vendor=tushare 

首次数据采集耗时较长,后面会增量更新,数据量级如下:

image

4.2、因子计算

基本数据采集完毕后,使用如下命令计算预定义好的因子,首次计算时间依然会比较长:

finhack factor run

计算完毕后,将在data/factors目录下产生600余个预先定义好的因子:

image

4.3、策略回测

框架自带了3个示例策略,我们选择一个小市值策略进行演示(该策略仅用作框架规则演示,无实际投资意义),执行

finhack trader run --strategy=SmallCapStrategy
image

执行完毕后命令行中显示结果如下(截图未显示全绩效评估指标):

image

4.4、策略代码

简单参考一下策略代码的样式,具体策略规则会在别的文档中详细说明:

import datetime
import os
import random
from finhack.factor.default.factorManager import factorManager
## 初始化函数,设定要操作的股票、基准等等
def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000001.SH')
    # True为开启动态复权模式,使用真实价格交易
    set_option('use_real_price', True) 
    # 设定成交量比例
    set_option('order_volume_ratio', 1)
    # # 股票类交易手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(open_tax=0, close_tax=0.001, \
                             open_commission=0.0003, close_commission=0.0003,\
                             close_today_commission=0, min_commission=5), type='stock')
    
    # 为股票设定滑点为百分比滑点                       
    set_slippage(PriceRelatedSlippage(0.00246),type='stock')
    # 持仓数量
    g.stocknum = 5
    # 交易日计时器
    g.days = 0 
    # 调仓频率
    g.refresh_rate = 15
    # 运行函数
    #inout_cash(100000)

    run_daily(trade, time="09:30")
    # run_daily(trade, time="8:05")
    
    g.factors=factorManager.getFactors(['pe_0','MACD_0','peTtm_0','pb_0','totalMv_0'])
    g.factors=g.factors.reset_index()

## 交易函数
def trade(context):
    if g.days%g.refresh_rate == 0:
        #print(context.portfolio.cash)
        sell_list = list(context.portfolio.positions.keys()) 
        if len(sell_list) > 0 :
            for stock in sell_list:
                order_target_value(stock, 0)  
    
        if len(context.portfolio.positions) < g.stocknum :
            Num = g.stocknum - len(context.portfolio.positions)
            Cash = context.portfolio.cash/Num
        else: 
            Cash = 0
    
        ## 选股
        now_date=context.current_dt.strftime('%Y%m%d')
        df = g.factors.query(f"trade_date =='{now_date}' & pe_0 > 0 & pb_0 < 2 & MACD_0<0 & peTtm_0<pe_0 & pe_0<50 & pe_0>10")
        df=df.sort_values(by='totalMv_0',ascending=True, inplace=False) 

        stock_list = df.head(g.stocknum)['ts_code'].tolist()
        ## 买入股票
        for stock in stock_list:
            if len(context.portfolio.positions.keys()) < g.stocknum:
                order_value(stock, Cash)

        # 天计数加一
        g.days = 1
    else:
        g.days += 1