Python版A股选股软件源代码,选股系统源代码,实现多种选股策略

本程序使用传统的[TuShare接口],并非需要捐赠的[pro接口]获取数据无限制;

另,由于TuShare的增量更新接口有bug(最近一个交易日的数据获取不到),所以每次计算前都是删除所有数据,全部重新获取。

本程序实现了若干种选股策略,大家可以自行选择其中的一到多种策略组合使用,参见work_flow.py

各策略中的end_date参数主要用于回测。

安装依赖:
根据不同的平台安装TA-Lib程序
Mac OS X

$ brew install ta-lib
Windows

下载 ta-lib-0.4.0-msvc.zip,解压到 C:\ta-lib
安装方法详见百度

Linux

下载 ta-lib-0.4.0-src.tar.gz :

$ untar and cd
$ ./configure --prefix=/usr
$ make
$ sudo make install
推荐使用Python3.8以上以及pip3
Python 依赖:
pip install -r requirements.txt
运行
本地运行
$ python main.py
运行结果查看日志文件sequoia.log

服务器端运行
用户也可以将本程序作为定时任务运行在服务端,需要做以下工作:

将config.yaml中的cron配置改为true,push.enable改为true
参考README_PUSH.md文档搭建 ejabberd 推送服务
客户端Android推荐使用 Conversations ,iOS没有开发者证书的话推送不了,有证书推荐使用 ChatSecure-iOS ,我采用的推送方案是ejabberd搭配Conversations。 效果如图
statistics strategy

如何回测
修改 work_flow.py#L61 中end为指定日期,格式为’YYYY-MM-DD’,如:

end = '2019-06-17'

运行截图:
在这里插入图片描述
在这里插入图片描述

main.py

# -*- encoding: UTF-8 -*-

import utils
import logging
import work_flow
import settings
import schedule
import time


def job():
    if utils.is_weekday():
        work_flow.process()


logging.basicConfig(format='%(asctime)s %(message)s', filename='sequoia.log')
logging.getLogger().setLevel(logging.INFO)
settings.init()

if settings.config['cron']:
    EXEC_TIME = "15:15"
    schedule.every().day.at(EXEC_TIME).do(job)

    while True:
        schedule.run_pending()
        time.sleep(1)
else:
    work_flow.process()

data_fetcher.py

# -*- encoding: UTF-8 -*-

import tushare as ts
import pandas as pd
import datetime
import logging
import settings
import talib as tl

import utils

import concurrent.futures

from pandas.tseries.offsets import *


# def update_data(code_name):
#     stock = code_name[0]
#     old_data = utils.read_data(code_name)
#     if not old_data.empty:
#         start_time = utils.next_weekday(old_data.iloc[-1].date)
#         current_time = datetime.datetime.now()
#         if start_time > current_time:
#             return
#
#         df = ts.get_k_data(stock, autype='qfq')
#         mask = (df['date'] >= start_time.strftime('%Y-%m-%d'))
#         appender = df.loc[mask]
#         if appender.empty:
#             return
#         else:
#             return appender


def init_data(code_name):
    stock = code_name[0]
    data = ts.get_k_data(stock, autype='qfq')

    if data is None or data.empty:
        logging.debug("股票:"+stock+" 没有数据,略过...")
        return

    data['p_change'] = tl.ROC(data['close'], 1)

    return data


def run(stocks):
    append_mode = False
    update_fun = init_data

    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        future_to_stock = {executor.submit(update_fun, stock): stock for stock in stocks}
        for future in concurrent.futures.as_completed(future_to_stock):
            stock = future_to_stock[future]
            try:
                data = future.result()
                data['code'] = data['code'].apply(lambda x: str(x))
                if data is not None:
                    file_name = stock[0] + '-' + stock[1] + '.h5'
                    data.to_hdf(settings.config['data_dir'] + "/" + file_name, 'data', append=append_mode, format='table')
            except Exception as exc:
                print('%s(%r) generated an exception: %s' % (stock[1], stock[0], exc))

work_flow.py

# -*- encoding: UTF-8 -*-

import data_fetcher
import utils
import strategy.enter as enter
from strategy import turtle_trade
from strategy import backtrace_ma250
from strategy import breakthrough_platform
from strategy import parking_apron
from strategy import low_backtrace_increase
from strategy import keep_increasing
import tushare as ts
import push
import logging
import db
import time
import datetime
import urllib
import settings
import pandas as pd


def process():
    logging.info("************************ process start ***************************************")
    try:
        all_data = ts.get_today_all()
        subset = all_data[['code', 'name', 'nmc']]
        subset.to_csv(settings.config['stocks_file'], index=None, header=True)
        stocks = [tuple(x) for x in subset.values]
        statistics(all_data, stocks)
    except urllib.error.URLError as e:
        subset = pd.read_csv(settings.config['stocks_file'])
        subset['code'] = subset['code'].astype(str)
        stocks = [tuple(x) for x in subset.values]

    if utils.need_update_data():
        utils.prepare()
        data_fetcher.run(stocks)
        check_exit()

    strategies = {
        '海龟交易法则': turtle_trade.check_enter,
        '放量上涨': enter.check_volume,
        '突破平台': breakthrough_platform.check,
        '均线多头': keep_increasing.check,
        '无大幅回撤': low_backtrace_increase.check,
        '停机坪': parking_apron.check,
        '回踩年线': backtrace_ma250.check,
    }

    if datetime.datetime.now().weekday() == 0:
        strategies['均线多头'] = keep_increasing.check

    for strategy, strategy_func in strategies.items():
        check(stocks, strategy, strategy_func)
        time.sleep(2)

    logging.info("************************ process   end ***************************************")


def check(stocks, strategy, strategy_func):
    end = None
    m_filter = check_enter(end_date=end, strategy_fun=strategy_func)
    results = list(filter(m_filter, stocks))
    push.strategy('**************"{0}"**************\n{1}\n**************"{0}"**************\n'.format(strategy, results))


def check_enter(end_date=None, strategy_fun=enter.check_volume):
    def end_date_filter(code_name):
        data = utils.read_data(code_name)
        if data is None:
            return False
        else:
            return strategy_fun(code_name, data, end_date=end_date)
        # if result:
        #     message = turtle_trade.calculate(code_name, data)
        #     push.strategy("{0} {1}".format(code_name, message))

    return end_date_filter


# 统计数据
def statistics(all_data, stocks):
    limitup = len(all_data.loc[(all_data['changepercent'] >= 9.5)])
    limitdown = len(all_data.loc[(all_data['changepercent'] <= -9.5)])

    up5 = len(all_data.loc[(all_data['changepercent'] >= 5)])
    down5 = len(all_data.loc[(all_data['changepercent'] <= -5)])

    def ma250(stock):
        stock_data = utils.read_data(stock)
        return enter.check_ma(stock, stock_data)

    ma250_count = len(list(filter(ma250, stocks)))

    msg = "涨停数:{}   跌停数:{}\n涨幅大于5%数:{}  跌幅大于5%数:{}\n年线以上个股数量:    {}"\
        .format(limitup, limitdown, up5, down5, ma250_count)
    push.statistics(msg)


def check_exit():
    t_shelve = db.ShelvePersistence()
    file = t_shelve.open()
    for key in file:
        code_name = file[key]['code_name']
        data = utils.read_data(code_name)
        if turtle_trade.check_exit(code_name, data):
            push.strategy("{0} 达到退出条件".format(code_name))
            del file[key]
        elif turtle_trade.check_stop(code_name, data, file[key]):
            push.strategy("{0} 达到止损条件".format(code_name))
            del file[key]

    file.close()


完整程序代码下载:A股选股软件源代码

Python代码大全,海量代码任你下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python代码大全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值