我用python实现了一个量化选股程序

背景

近期在学习数据分析,在课程最后老师讲了一下通过量化分析选择股票的案例,感觉挺有意思的,恰好周围也有人在炒股票,干脆自己做一个软件来实践一下学到的知识。课程上主要用python相关库来处理比特币的数据,数据量也不大,但是理解原理之后我们可以举一反三。

首先来回顾一下主要的知识点,选择股票的时候会用到两个重要的指标RSV、KDJ。他们的定义见下面的课件截图,具体的内容我就不阐述了,因为我是非金融专业的,对这些词汇解释起来有点吃力。我们只要记住这两个指标如何计算,以及后面如何使用即可

KDJ指标定义

image.png

image.png

image.png

计算K指标

image.png

计算D指标

image.png

计算J指标

image.png

实验原理

老师在课程中讲到K和D都是反映股票变化趋势的,K要比D灵敏,当K值上穿D值时(第一次出现K>D)时代表股票可能出现向上反弹,此时是买入时机,当K下穿D值时(第一次出现K<D)时,代表股票有较大概率出现下跌,此时是卖出时机。
通过利用这个方法,我们可以在4000多支股票中筛选出若干可能出现反弹的股票,然后再用人的经验和其他方面的信息选出心仪的股票了。
我们的实验思路是:

  1. 先从网络上获取过去半年 4000支股票的交易信息,包括日期(date)、最高价(high)、最低价(low)、开盘价(open)、收盘价(close),将这些信息存储到stockbars表中
  2. 用python程序读取stockbars表中的每条记录,计算出rsv指标存储到stockrsvs表中
  3. 最后用python程序读取stockrsvs表,计算出k、d、j三个指标
  4. 最后我们用SQL语句查询数据库,每个人可以基于RSV、k、d、j这四个值自由定义查询方式

这里我们用到了kdj金融知识、python编程知识、SQL语言以及数据库相关的内容,也算是一次综合性的演练了。还可以利用Sugar来在线绘制大屏小白学数据分析–工具篇(可视化Sugar)

实验过程

实验环境准备

我们用到了python开发环境,这里我们用docker直接获取一个镜像使用,省的安装一堆乱七八糟的依赖,当然你也可以按照自己的喜好来自行安装

Docker pull docker.io/python

数据库我们使用了一个免费的云数据库MemFire Cloud ,他提供了公网IP以及可视化的SQL编辑器方便我们后续查询数据

image.png

实验步骤和代码

获取原始数据

image.png

image.png

计算RSV指标

   for stock in stocks:
        i += 1
        bars = session.query(StockBar).filter(
                    StockBar.stock_id == stock.id
                ).order_by(StockBar.date.asc()).all()

        if len(bars) < window:
            print("stock %s  bar less than window %s real %s cal next stock" % (stock.id, window, len(bars)))
            continue

        for bar in bars:
            rsv = session.query(StockRSV).filter(
                    StockRSV.id == bar.stock_id + "_" + str(bar.date)
                ).first()


            if rsv is not None:
                print("rsv: id:%s stock_id:%s, date:%s,rsv value:%s cal next bar" % (
                    rsv.id, rsv.stock_id, rsv.date, rsv.rsv
                ))
                continue

            prevbars = session.query(StockBar).filter(
                    StockBar.stock_id == stock.id,
                    StockBar.date <= bar.date
                ).order_by(StockBar.date.desc()).limit(window).all()

            if len(prevbars) < window:
                print("stock %s date %s perv less than window %s cal next date" % (stock.id, bar.date, window))
                continue

            for prevbar in prevbars:
                print("prevbar: id %s , stock_id:%s, date:%s, open:%s, high:%s, low:%s, close:%s" % 
                        (prevbar.id, prevbar.stock_id, prevbar.date, prevbar.open, prevbar.high, prevbar.low, prevbar.close))

            low = prevbars[0].low
            high = prevbars[0].high
            lastopen = prevbars[0].open
            lastclose = prevbars[0].close

            for prevbar in prevbars:
                if prevbar.high >= high:
                    high = prevbar.high
                if prevbar.low <= low:
                    low = prevbar.low
            
            print("rsv: stock_id %s, date:%s lastopen:%s, lastclose:%s, high:%s, low:%s" % 
                    ( bar.stock_id, bar.date, lastopen, lastclose, high, low))

            stockrsv = StockRSV(id = bar.stock_id + "_" + str(bar.date),
                stock_id = bar.stock_id,
                date = bar.date,
                rsv = 100 * (lastclose - low) / (high - low))
            session.add(stockrsv)
            session.commit()

计算结果

image.png

计算KDJ指标

 for stock in stocks:
        i += 1
        rsvs = session.query(StockRSV).filter(
                    StockRSV.stock_id == stock.id
                ).order_by(StockRSV.date.asc()).all()

        if len(rsvs) < 1:
            print("stock %s  rsv less than window %s real %s cal next stock" % (stock.id, 1, len(rsvs)))
            continue

        for stockrsv in rsvs:
            curkdj = session.query(StockKDJ).filter(
                    StockKDJ.id == stockrsv.stock_id + "_" + str(stockrsv.date)
                ).first()
            if curkdj is not None:
                print("kdj id:%s, stock_id:%s,date:%s,k:%s, d:%s,j:%s exist cal next" % (
                    curkdj.id, curkdj.stock_id, curkdj.date, curkdj.k, curkdj.d, curkdj.j
                ))
                continue
            
            lastkdj = session.query(StockKDJ).filter(
                    StockKDJ.stock_id == stockrsv.stock_id,
                    StockKDJ.date < stockrsv.date
                ).order_by(StockKDJ.date.desc()).limit(1).first()


            lastkvalue = 0
            lastdvalue = 0

            if lastkdj is not None:
                lastkvalue = lastkdj.k
                lastdvalue = lastkdj.d

            stockkdj = StockKDJ(id = stockrsv.stock_id + "_" + str(stockrsv.date),
                stock_id = stockrsv.stock_id,
                date = stockrsv.date,
                k = curkvalue,
                d = curdvalue,
                j = 0)
            session.add(stockkdj)
            session.commit()

计算结果

image.png

使用SQL选股

我们选择最近RSV值较低,且K>D 的十只股票

image.png

到股票软件上查看这几只股票的趋势图

image.png

实验总结

通过这次实验,我们探索了一种方法,使用python获取股票数据,因为记录数较多且计算过程无法递归,只能通过循环的方式结合数据库循环计算指标。最后将计算的结果存储在数据库中,利用SQL语言的丰富语义,可以灵活的验证各种选股的模型。虽然本次实验得出来的选股方法可能不如专业机构的准确,但是胜在灵活多变,你可以结合自己的经验调整。

  • 4
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值