分享

Quantlab4.0框架代码发布:支持零代码快速创建策略(代码+全市场数据下载)

 AI量化实验室 2024-05-24 发布于北京

原创文章第543篇,专注“AI量化投资、世界运行的规律、个人成长与财富自由"。

本次改动比较大,底层引擎更换了。

使用更加简洁了,代码量更少了。

1、去除了wxpython壳。

2、使用bt引擎。

3、支持低代码创建与回测策略。

代码已经提交,大家可前往下载,含全市场数据:

大家下载代码之后,安装好依赖,直接运行main即可:

写一个策略特别简单:

第一步:选择交易标的,这里咱们选择沪深300和创业板,两个代表大小盘的ETF。

第二步:

新增一个动量因子:

第三步:

交易规则配置:

左边是进场规则 ,右边是离场规则:

第四步:一些回测细节,由于这个策略比较简单,保持默认参数即可:

点击保存策略,或者回测。

年化20%,还不错哦。

数据在如下位置:

送一张优惠券:

gui代码如下:

import os
from dataclasses import asdict

import streamlit as st

st.session_state['rules_buy'] = []
st.session_state['rules_sell'] = []

import requests
import pandas as pd

from config import DATA_DIR
from task import Task, run_task, task_from_json
# from engine.engine import Engine
from datetime import datetime
from . import gui_const

url = 'http:///api/funds'
st.session_state['features'] = []
st.session_state['feature_names'] = []
g_feature_names = st.session_state['feature_names']
g_features = st.session_state['features']

st.session_state['symbols'] = []
g_symbols = st.session_state['symbols']


st.session_state['task'] = Task()

g_rules_buy = st.session_state['rules_buy']
g_rules_sell = st.session_state['rules_sell']


def show_tasks():
directory = DATA_DIR.joinpath('tasks')

# os.listdir() 列出目录下的所有文件和目录名
tasks = []
for filename in os.listdir(directory.resolve()):
file_path = os.path.join(directory, filename)
if os.path.isfile(file_path): # 判断是否是文件
print(f'文件: {file_path}')
tasks.append(filename)
tasks.insert(0, '创建新策略')
task_name = st.selectbox('本地策略列表:', options=tasks, index=0)
if task_name and task_name != '创建新策略':
task_ = task_from_json(filename)
st.session_state['feature_names'] = task_.feature_names
st.session_state['features'] = task_.features
st.session_state['rules_buy'] = task_.rules_buy
st.session_state['rules_sell'] = task_.rules_sell
# st.write(task_)
else:
task_ = Task()
st.session_state['task'] = task_
g_rules_buy = task_.rules_buy
g_rules_sell = task_.rules_sell

# st.write(task_)


@st.cache_data
def get_funds():
datas = requests.get(url).json()
dict_data = {item['symbol']: item['name'] + '({})'.format(item['symbol']) for item in datas}
return dict_data


def select_funds():
def _select_funds_format(x):
return get_funds()[x]

# task.symbols = list(get_funds().keys())
task = st.session_state['task']
symbol_selected = st.multiselect(label='请选择基金:', options=list(get_funds().keys()),
format_func=lambda x: _select_funds_format(x), default=task.symbols)
task.symbols = symbol_selected


def select_period():
task = st.session_state['task']
periods = {'RunDaily': '每天运行', 'RunWeekly': '每周运行', 'RunMonthly': '每月运行', 'RunQuarterly': '每季度运行',
'RunYealy': '每年运行',
'RunDays': '自定义天数'}

def _period_format(x):
return periods[x]

period = st.selectbox(label='请选择调仓周期', index=0, options=list(periods.keys()),
format_func=lambda x: _period_format(x))
if period == 'RunDays':
days = st.number_input(label='请输入天数', min_value=1, max_value=365)
task.algo_period_days = days
task.algo_period = period


def select_weights():
task = st.session_state['task']
weights = {
'WeighEqually': '等权分配',
'WeighFix': '固定权重',
'WeighERC': '风险平价'
}

def _weight_format(x):
return weights[x]

weight = st.selectbox(label='请选择权重分配', options=list(weights.keys()), format_func=lambda x: _weight_format(x))
if weight == 'WeightFix':
fix_weigths = st.text_input(label='请输入权重(逗号分隔)', value='[]')
task.algo_weight_fix = eval(fix_weigths)
task.algo_weight = weight


def add_features():
factors = list(gui_const.ind_dict.keys())
task = st.session_state['task']
g_feature_names = st.session_state['feature_names']
g_features = st.session_state['features']


ind_name = st.selectbox('选择因子', options=factors, key='select_features', index=0)
if st.button('新增'):
ind = gui_const.ind_dict[ind_name]
g_feature_names.append(ind.name)
g_features.append(ind.expr)

count = 0

for i, (name, feature) in enumerate(zip(g_feature_names, g_features)):
col1, col2, col3 = st.columns(3)
with col1:
f = st.text_input(label='因子名', value=name, key=feature + str(count))
g_feature_names[i] = f
with col2:
n = st.text_input(label='表达式', value=feature, key=name + str(count))
g_features[i] = n
with col3:
if st.button('删除', key='btn' + str(count)):
g_feature_names.remove(name)
g_features.remove(feature)
st.rerun()
count += 1
task.features = g_features
task.feature_names = g_feature_names


def add_rule(rules, rule_type='buy'):
task = st.session_state['task']
f = st.selectbox(label='因子', options=task.feature_names, key=rule_type)
if st.button('添加', key='rule_add' + rule_type):
print('f name>>', f)
r = gui_const.Rule(f)
rules.append(r.get_expr())

#st.write(rules)
for i, rule_str in enumerate(rules):

rule = gui_const.Rule().parse_from(rule_str)
col1, col2, col3, col4 = st.columns(4)
with col1:
# st.writee(task.feature_names)
rule.feature_name = st.selectbox(label='因子', options=task.feature_names, key='factor' + rule_type + str(i))
with col2:
op_index = 0
if rule.ops == '=':
op_index = 1
elif rule.ops == "<":
op_index = 2
rule.ops = st.selectbox(label='比较', options=['>', '=', '<'], key='ops' + rule_type + str(i), index=op_index)
with col3:
rule.value = st.number_input(label='', value=float(rule.value), min_value=-100.0, step=0.01,
max_value=100.0, key='value' + rule_type + str(i))

with col4:
if st.button('删除', key='rule_delete' + rule_type + str(i)):
rules.remove(rule_str)
st.rerun()
rules[i] = rule.get_expr()

def buy_and_sell_rules():
task = st.session_state['task']
g_rules_buy = st.session_state['rules_buy']
g_rules_sell = st.session_state['rules_sell']
col1, col2 = st.columns(2)
with col1:
add_rule(g_rules_buy)
task.rules_buy = g_rules_buy

with col2:
add_rule(g_rules_sell, rule_type='sell')
task.rules_sell = g_rules_sell


def order_by():
task = st.session_state['task']
index = 0
if task.order_by and task.order_by in task.feature_names:
index = task.feature_names.index(task.order_by)
order_by = st.selectbox(label='排序因子', options=task.feature_names, index=index)
top_K = st.number_input(label='top K = ', value=task.topK)
# drop_N = st.number_input(label='排除前N = ', value=task.dropN)
task.order_by = order_by
task.topK = top_K
# task.dropN = drop_N


def backtest(task: Task):
if st.button(label='开始回测'):
with st.spinner('回测进行中,请稍后...'):
res = run_task(task)
df = res.prices
ratio = res.stats
orders_df = res.get_transactions()

col1, col2 = st.columns(2)
with col1:
st.write(ratio)
print(ratio)
with col2:
st.line_chart(df)

st.write(orders_df)


def build():
# with col2:
task = st.session_state['task']
tab1, tab2, tab3, tab4 = st.tabs(["选择ETF", "因子配置", "交易规则", "回测设置"])
with tab1:
select_funds()
with tab2:
add_features()
with tab3:
# add_features(task)
buy_and_sell_rules()

with tab4:
col1, col2, col3 = st.columns(3)
with col1:
order_by()

with col2:
select_period()
select_weights()

name = st.text_input(label='策略名称', value=task.name)
task.name = name

col1, col2 = st.columns(2)
with col1:
date_start = st.date_input(label='起始日期', value=datetime(2010, 1, 1))
task.start_date = date_start.strftime("%Y%m%d")
with col2:
date_end = st.date_input(label='结束日期')
task.end_date = date_end.strftime("%Y%m%d")
if st.button(label='保存策略'):
json_data = task.to_json(task.name)
import json
from config import DATA_DIR
with open(DATA_DIR.joinpath('tasks').joinpath(name + '.json'), "w", encoding='UTF-8') as f:
json.dump(asdict(task), f, ensure_ascii=False)
backtest(task)
#st.write(task)

历史文章:

代码发布:AlphaGPT v0.1——基于大模型的智能因子挖掘框架(代码+数据下载)

AI量化实验室——2024量化投资的星辰大海

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约