datochan / DTGear

分析大盘和基金的小程序
41 stars 32 forks source link

关于复权 #1

Closed abc100m closed 5 years ago

abc100m commented 5 years ago

一般看股票都是要前复权数据。 请问下,获取了股票日K线数据,还有股票送转派息数据。怎么样计算前复权? 有没有通用算法来计算得到前复权日K线数据。

datochan commented 5 years ago

我代码里有计算后复权,计算前复权的思路也是一样的。只是感觉计算前复权每次都要全量计算比较麻烦。 如果你需要详细的计算思路,我当时参考的这篇文章: 复权的精确计算——持有封基说股市之四十一

你看下,希望对你有帮助!

abc100m commented 5 years ago

谢谢。 请问一下,哪个文件的哪段代码,是后复权计数? 那个复权数据我没看明白,不知道要怎么用。

datochan commented 5 years ago

/app/cmd/convert.py

这里面有计算后复权的命令:

@convert.command(help="计算后复权价")
def fixed():
    db_client = MongoDBClient(config.get("db").get("mongodb"), config.get("db").get("database"))

    base_df = stocks.stock_a_list()
    bonus_df = bonus.bonus_with(None)

    for index, row in base_df.iterrows():
        try:
            prev_close = 0
            prev_fixed_close = 0

            print("计算 %d-%s 的后复权数据" % (row["market"], row["code"]))

            stock_day_list = db_client.find_stock_list(_filter={"code": row['code'], "market": row["market"]},
                                                       _sort=[("date", pymongo.ASCENDING)],
                                                       _fields={"date":1, "close":1})
            if len(stock_day_list) <= 0:
                # 股票本身没有交易量无需复权
                continue

            stock_day_df = pd.DataFrame(stock_day_list, columns=['date', 'close'])

            try:
                item_last = db_client.find_stock_item(_filter={"code": row['code'], "market": row["market"],
                                                               "fixed": {"$exists": True}},
                                                      _sort=[("date", pymongo.DESCENDING)])

                if item_last is not None and len(item_last) > 0:
                    # 如果之前计算过后复权价,则无需重头计算
                    last_day_df = stock_day_df[stock_day_df["date"] == item_last['date']]

                    prev_close = last_day_df.ix[last_day_df.index.values[0]]["close"]
                    prev_fixed_close = item_last["fixed"]

                    stock_day_df = stock_day_df[stock_day_df.index > last_day_df.index.values[0]]

            except FileNotFoundError as ex:
                # 如果从来没计算过后复权价则不管
                pass

            filter_df = bonus_df[(bonus_df["type"] == 1) & (bonus_df["code"] == row["code"])]
            filter_df = filter_df.sort_values(['date'], ascending=True)
            for idx, item in stock_day_df.iterrows():
                money = 0  # 分红
                count = 0  # 送股数

                item_df = filter_df[filter_df["date"] == int(item["date"])]
                if len(item_df) > 0:
                    money = item_df.ix[item_df.index.values[0]]["money"] / 10
                    count = item_df.ix[item_df.index.values[0]]["count"] / 10

                # 除息除权日当天复权后的涨幅 =(当天不复权收盘价 *(1 + 每股送股数量)+每股分红金额) / 上一个交易日的不复权收盘价
                # 复权收盘价 = 上一个交易日的复权收盘价 *(1 + 复权涨幅)
                if prev_close > 0:
                    daily_rate_close = (item["close"] * (1 + count) + money) / prev_close
                    prev_fixed_close = prev_fixed_close * daily_rate_close

                else:
                    prev_fixed_close = item["close"]

                prev_close = item["close"]
                db_client.upsert_one(_filter={"code": str(row["code"]), "market": row["market"], "date": str(item["date"])},
                                     _value={"fixed": prev_fixed_close})

        except FileNotFoundError as ex:
            continue
abc100m commented 5 years ago

很给力,谢谢哈