策略1:使用python+mongodb实现股票网格交易代码----附python源码

使用python+mongodb实现网格交易的思路:

网格,顾名思义,就是低买高卖,实现方案是用python,对某只股票的历史数据:

  1. 从x天开始算(当天就买入)
  2. 设定一个预期卖出价格,比如,比上次买入价格盈利5%,则卖出
  3. 设定一个预期买入价格,比如,比上次买入价格下跌5%,再次买入

由于还需要考虑其他问题,比如:

  1. 买入的股数,必须是100的整数倍
  2. 当天买入的份额,当天是不能卖的
  3. 如果股价一飞冲天,会不会卖飞?为了解决这个问题,我们使用一个数值:“累计买入次数”,买入+1,卖出-1,只需要观察数值的大小,就知道最大会卖飞多少,那么对应的,考虑为其建底仓。
  4. 股价会不会一直下跌?理论上是会的,我们还是使用“累计买入次数”这个变量,来看极限情况下,最多买入多少次(考虑了卖出-1)

系列文章:

  1. 策略1:使用python+mongodb实现股票网格交易代码----附python源码
  2. 使用matplotlib画k线(2条k线同列)----附python源码
  3. 策略3:动态再平衡----附python源代码

标的选择

这个是很多的,比如我常看的是下面这几个,比较稳健:

数据抓取

抓取历史数据,有很多的方案,比如

  • Tushare:https://www.tushare.pro/
  • 万得api
  • 爬虫(我用过搜狐证券:https://q.stock.sohu.com/cn/512010/lshq.shtml)

网格策略

变量描述

方案跟最开始的描述一致,代码中用到的一些变量

self.collection_detail_name = '策略2-网格-明细'+security
self.collection_summary_name = '策略2-网格-汇总'+security
super().__init__()
####################  计算数据  ########################
self.symbol = security
self.collection_name = security
self.mongo_util = MongoUtil()
self.start_date = start_date
##################  策略过程数据  #######################
self.last_buy_price = 0.000
# 预期买入价格
self.expect_buy_price = 0.000
# 预期卖出价格(根据最近一次买入价格计算) self.last_buy_price*(1+self.expect_percent)
self.expect_sell_price = 0.000
# 最多加仓多少次
self.buy_count = 0
self.sell_count = 0
# 最大浮亏金额
self.lose_total_money = 0.000
# 最大浮亏比例。 比如4.323%,这里就是4.323,不需要%。由于收益率是最终数据,此数据记录中间过程
self.lose_percent = 0.000
# 持有时间(从买到卖总天数,非交易天数,是自然日)
self.hold_days = 0
#####################  持仓情况  ########################
# cost: 成本价; capital:本金;shares:持有份额;benefit:收益;benefit_rate:收益率(不包含%)
# transactions: 交易信息 {'date': '', 'money': 0.000, 'shares':0, 'direction': '买入或卖出'}
self.hold_meta = {'cost': 0.000, 'capital': 0.000, 'shares': 0, 'benefit': 0.000, 'benefit_rate': 0.000,
'transactions': []}
#####################  达标目标  ########################
# 预期达标比例,例如盈利10%,就是0.1
self.expect_percent = 0.05
# 每次买入金额(这个还需要根据实际买入份额计算100整数倍)
self.per_buy_capital = 10000

开始测算

计算的时候,只需要如下:

# security是股票代码,date是希望从这一天开始测算,理论上随便选取哪天都可以,这样的话,可以策略在高点回落的极端场景,比如2018年以及之后的走势
strategy_meta = {"security": "SH601939", 'date': '2018-01-02'}
this = StrategyGrid(security=strategy_meta['security'], start_date=strategy_meta['date'])
# 删除mongodb中的旧的测算数据
this.delete_collection()
# 开始测算
this.run()

结果分析

这个是重头戏,先贴上来测算的结果(如有不对,麻烦指出)

标题头部:

_id:mongodb的唯一键

Benefit:利润,赚的钱

Benefit_rate:利润率

Buy_count: 前文解释过,是统计的历史"买入-卖出"次数

Capital:本金

cost:成本

date:交易日期(买入或卖出日期)

direction:交易方向(买入或卖出)

money:买入或卖出金额

price:买入或卖出价格

security:股票代码

Shares: 当前持仓数量

Start_date:测算的开始日期

  • 从2018-01-02开始,总共交易了多少次?买入和卖出各多少?

    共79次,买入40次,卖出39次

  • buy_count最大和最小多少?

    buy_count代表的是最多买入多少笔(最多加仓次数),最多卖出多少笔(卖飞),还是比较重要的

    • 最大:5

    • 最小:-3


      后续还会增加matplotlib进行可视化显示,比较好分析数据。

部分源码

import math

from Strategies.PercentCustom import PercentCustom
from utils.mongo_util.MongoUtil import MongoUtil


class StrategyGrid:

    def __init__(self, security, start_date) -> None:
        self.collection_detail_name = '策略2-网格-明细'+security
        self.collection_summary_name = '策略2-网格-汇总'+security
        super().__init__()
        ####################  计算数据  ########################
        self.symbol = security
        self.collection_name = security
        self.mongo_util = MongoUtil()
        self.start_date = start_date
        ##################  策略过程数据  #######################
        self.last_buy_price = 0.000
        # 预期买入价格
        self.expect_buy_price = 0.000
        # 预期卖出价格(根据最近一次买入价格计算) self.last_buy_price*(1+self.expect_percent)
        self.expect_sell_price = 0.000
        # 最多加仓多少次
        self.buy_count = 0
        self.sell_count = 0
        # 最大浮亏金额
        self.lose_total_money = 0.000
        # 最大浮亏比例。 比如4.323%,这里就是4.323,不需要%。由于收益率是最终数据,此数据记录中间过程
        self.lose_percent = 0.000
        # 持有时间(从买到卖总天数,非交易天数,是自然日)
        self.hold_days = 0
        #####################  持仓情况  ########################
        # cost: 成本价; capital:本金;shares:持有份额;benefit:收益;benefit_rate:收益率(不包含%)
        # transactions: 交易信息 {'date': '', 'money': 0.000, 'shares':0, 'direction': '买入或卖出'}
        self.hold_meta = {'cost': 0.000, 'capital': 0.000, 'shares': 0, 'benefit': 0.000, 'benefit_rate': 0.000,
                          'transactions': []}
        #####################  达标目标  ########################
        # 预期达标比例,例如盈利10%,就是0.1
        self.expect_percent = 0.05
        # 每次买入金额(这个还需要根据实际买入份额计算100整数倍)
        self.per_buy_capital = 10000

    def delete_collection(self):
        self.mongo_util.db[self.collection_detail_name].delete_many({})

    def run(self):
        start_record = self.mongo_util.db[self.collection_name].find_one({'date': self.start_date})
        start_shares = this.cal_shares_by_price(start_record['close'])
        start_money = start_shares * start_record['close']
        this.buy(date=start_record['date'], money=start_money, shares=start_shares, price=start_record['close'])
        # 下面这2个在this.buy已经计算过了,这里就不用再计算了
        # self.next_buy_price = cal_next_buy_price(start_record['close'])
        # self.expect_sell_price = this.cal_expect_sell_price(start_record['close'])
        # 从MongoDB读取数据,按照日期升序,即由远及近,默认1为升序,-1为降序
        # cursor = self.mongo_util.load_all_data(self.collection_name)
        cursor = self.mongo_util.db[self.collection_name].find({"date": {"$gt": self.start_date}}).sort("date", 1)
        for record in cursor:
            print('当天数据\n' + str(record) + '\n')
            print('预期买入价格' + str(self.expect_buy_price) + '\n')
            # 遍历循环
            # 持有时间(从买到卖总天数,非交易天数,是自然日)
            self.hold_days += 1
            # 因为由于可能下跌幅度较大,需要计算可买入的价格。
            while True:
                print('预期买入价格' + str(self.expect_buy_price))
                if record['low'] <= self.expect_buy_price:
                    print('当天最低价' + str(record['low']))
                    # 此时按照 self.expect_buy_price 进行买入
                    shares = this.cal_shares_by_price(self.expect_buy_price)
                    money = shares * self.expect_buy_price
                    this.buy(date=record['date'], money=money, shares=shares, price=self.expect_buy_price)
                    # 买入后,期望买入价格变化(由于在this.buy已经计算了下一个买入价格,所以这里就不需要再次计算了,直接使用即可)
                    print('预期买入价格(重新计算)' + str(self.expect_buy_price))
                else:
                    print('当天最低价' + str(record['low']) + ' > ' + str(self.expect_buy_price) + ',当天计算结束')
                    break
            while True:
                print('预期卖出价格' + str(self.expect_sell_price))
                if record['high'] >= self.expect_sell_price:
                    print('当天最高价' + str(record['high']))
                    # 此时按照 self.expect_sell_price 进行卖出
                    shares = this.cal_shares_by_price(self.expect_sell_price)
                    money = shares * self.expect_sell_price
                    this.sell(date=record['date'], money=money, shares=shares, price=self.expect_sell_price)
                    # 卖出后,期望卖出价格变化(由于在this.sell已经计算了下一个卖出价格,所以这里就不需要再次计算了,直接使用即可)
                    print('预期卖出价格(重新计算)' + str(self.expect_sell_price))
                else:
                    print('当天最高价' + str(record['high']) + ' < ' + str(self.expect_sell_price) + ',当天计算结束')
                    break

    def cal_shares_by_price(self, current_price):
        """
        总结:根据股价,计算买入的份额 = math.floor(1000/股价/100)*100
        :param current_price:
        :return:
        """
        return math.ceil(self.per_buy_capital / current_price / 100) * 100

    def buy(self, date, money, shares, price):
        """
        执行买入动作,传入买入日期,买入的金额。买入时,会触发下面的数据计算:
        1. "持仓情况"重新计算
        2. "策略过程数据"更新
        :param date: 交易日期,字符串
        :param money: 本次买入金额
        :param shares: 本次买入份额
        :param price: 交易价格
        :return:
        """
        self.buy_count += 1
        print('当前总买入次数' + str(self.buy_count))
        # cost 成本价=(本次买入金额 + capital)/(shares + 本次买入份额)
        self.hold_meta['cost'] = (money + self.hold_meta['capital']) / (self.hold_meta['shares'] + shares)
        # capital 本金 = capital + 本次买入金额
        self.hold_meta['capital'] = self.hold_meta['capital'] + money
        # shares 持有份额 = shares + 本次买入份额
        self.hold_meta['shares'] = self.hold_meta['shares'] + shares
        # benefit 收益 = (当前价格 - 成本价) * 持有份额
        self.hold_meta['benefit'] = (price - self.hold_meta['cost']) * self.hold_meta['shares']
        # benefit_rate 收益率 = 收益/本金
        self.hold_meta['benefit_rate'] = self.hold_meta['benefit']/self.hold_meta['capital']
        # transactions 交易信息 {'date': '', 'money': 0.000, 'shares':0, 'direction': '买入或卖出'}
        this_transaction = {'uuid': self.symbol + '|' + self.start_date + '|' + date + '|' + str(self.buy_count),
                            'buy_count': self.buy_count, 'security': self.symbol, 'start_date': self.start_date,
                            'date': date, 'money': money, 'direction': '买入', 'price':price,
                            'cost': self.hold_meta['cost'], 'capital': self.hold_meta['capital'], 'shares': self.hold_meta['shares'],
                            'benefit': self.hold_meta['benefit'], 'benefit_rate': self.hold_meta['benefit_rate']
                            }
        self.hold_meta['transactions'].append(this_transaction)
        # 将本次交易数据存储到MongoDB
        self.mongo_util.save_or_update_by_uuid(mongodb_collection=self.collection_detail_name, data_dict=this_transaction)

        # 预期买入价格重新计算
        self.expect_buy_price = self.cal_expect_buy_price(price)
        # 预期卖出价格
        self.expect_sell_price = self.cal_expect_sell_price(price)
        # 最大浮亏金额 (因为只有下跌才会买,所以,就按照当前价格和成本计算即可)
        self.lose_total_money = self.hold_meta['benefit']
        # 最大浮亏比例。 比如4.323%,这里就是4.323,不需要%。由于收益率是最终数据,此数据记录中间过程
        self.lose_percent = self.hold_meta['benefit_rate']

    def sell(self, date, money, shares, price):
        """
        执行卖出动作,传入卖出日期,卖出的金额。卖出时,会触发下面的数据计算:
        1. "持仓情况"重新计算
        2. "策略过程数据"更新
        :param date: 交易日期,字符串
        :param money: 本次卖出金额
        :param shares: 本次卖出份额
        :param price: 交易价格
        :return:
        """
        self.sell_count += 1
        self.buy_count -= 1
        print('当前总卖出次数' + str(self.sell_count))
        # cost 成本价=(capital - 本次卖出金额)/(shares - 本次卖出份额)
        if (self.hold_meta['shares'] - shares) == 0:
            self.hold_meta['cost'] = 0
        else:
            self.hold_meta['cost'] = (self.hold_meta['capital'] - money) / (self.hold_meta['shares'] - shares)
        # capital 本金 = capital - 本次卖出金额
        self.hold_meta['capital'] = self.hold_meta['capital'] - money
        # shares 持有份额 = shares - 本次卖出份额
        self.hold_meta['shares'] = self.hold_meta['shares'] - shares
        # benefit 收益 = (当前价格 - 成本价) * 持有份额
        self.hold_meta['benefit'] = (price - self.hold_meta['cost']) * self.hold_meta['shares']
        # benefit_rate 收益率 = 收益/本金
        if self.hold_meta['capital'] != 0:
            self.hold_meta['benefit_rate'] = self.hold_meta['benefit'] / self.hold_meta['capital']
        else:
            self.hold_meta['benefit_rate'] = 0
        # transactions 交易信息 {'date': '', 'money': 0.000, 'shares':0, 'direction': '买入或卖出'}
        this_transaction = {'uuid': self.symbol + '|' + self.start_date + '|' + date + '|' + str(self.buy_count),
                            'buy_count': self.buy_count, 'security': self.symbol, 'start_date': self.start_date,
                            'date': date, 'money': money, 'direction': '卖出', 'price':price,
                            'cost': self.hold_meta['cost'], 'capital': self.hold_meta['capital'], 'shares': self.hold_meta['shares'],
                            'benefit': self.hold_meta['benefit'], 'benefit_rate': self.hold_meta['benefit_rate']
                            }
        self.hold_meta['transactions'].append(this_transaction)
        # 将本次交易数据存储到MongoDB
        self.mongo_util.save_or_update_by_uuid(mongodb_collection=self.collection_detail_name, data_dict=this_transaction)

        # 预期买入价格重新计算
        self.expect_buy_price = self.cal_expect_buy_price(price)
        # 预期卖出价格
        self.expect_sell_price = self.cal_expect_sell_price(price)
        # 最大浮亏金额 (因为只有下跌才会买,所以,就按照当前价格和成本计算即可)
        self.lose_total_money = self.hold_meta['benefit']
        # 最大浮亏比例。 比如4.323%,这里就是4.323,不需要%。由于收益率是最终数据,此数据记录中间过程
        self.lose_percent = self.hold_meta['benefit_rate']

    def cal_expect_sell_price(self, price):
        """
        根据当前成本价,计算预期卖出价格 price*(1+self.expect_percent)
        :return:
        """
        return price * (1 + self.expect_percent)

    def cal_expect_buy_price(self, price):
        """
        根据当前成本价,计算预期买入价格 price*(1-self.expect_percent)
        :return:
        """
        return price * (1 - self.expect_percent)

    def save_run_result(self, sell_record):
        """
        保存单次策略运行结果。比如计算 2018-01-02 这一天开始的策略计算,sell_record就是2018-01-02这天买入后,在x那天卖出。
        :param sell_record: 如果最终没有卖出,那么此为None
        :return:
        """
        sell_date = None
        sold = False
        earn_money = 0.000
        if sell_record is not None:
            sell_date = sell_record['date']
            sold = True
            earn_money = self.hold_meta['shares'] * (self.expect_sell_price - self.hold_meta['cost'])
        result_record = {'uuid': self.symbol + '|' + self.start_date, "security": self.symbol, "date": sell_record['date'],
                         '加仓次数': self.buy_count, '最大浮亏': self.lose_total_money, '最大浮亏比例': self.lose_percent,
                         '持有天数': self.hold_days, '成本价': self.hold_meta['cost'], '总买入本金': self.hold_meta['capital'],
                         '总份额': self.hold_meta['shares'], '卖出日期': sell_date, '卖出价格': self.expect_sell_price,
                         'sold': sold,
                         'earn_money': earn_money
                         }
        self.mongo_util.save_or_update_by_uuid(mongodb_collection=self.collection_summary_name, data_dict=result_record)


if __name__ == '__main__':

    strategy_meta = {"security": "SH512000", 'date': '2018-01-02'}
    this = StrategyGrid(security=strategy_meta['security'], start_date=strategy_meta['date'])
    this.delete_collection()
    this.run()


【资源说明】 基于Python实现的简单网格策略交易源码+使用说明.zip 策略说明 开仓:在盘口挂出买N和卖N,当你的买单或卖单完成后,再重新开启相应的仓位,保持你始终有买N和卖N的订单。 **KuCoin**拥有**level3交易数据、强大的撮合引擎、针对api用户提供的手续费折扣**,同时提供**sandbox环境**作为数据测试支撑,帮助你规避风险。 我们仅提供一个简单且不完备的交易策略使用时**请注意规避风险**,我们希望你能够**在sandbox环境配合其他参数或是策略进行测试调整,我们也不想你成为一个慈善家!!! 如何使用 * 安装Python * Windows系统请前往[Python](https://www.python.org/downloads/windows/)官网自行安装,64位请选择1,32位请选择2。 <img src="./img/python_download.png" style="zoom:50%" /> * 在开始安装时请注意将以下选项勾选: <img src="./img/python_win.png" style="zoom:40%" /> * MAC OS X安装 * 打开命令终端,输入以下命令安装Homebrew(安装过程中需要输入**电脑密码**): ```shell /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ``` * 在命令终端输入以下命令,安装Python3: ```shell brew install python ``` * 在命令终端输入以下命令,确认是否安装成功: ```shell python3 --version ``` Mac/Linux **在项目目录下**打开命令终端: ```shell cd simple-grid ``` * 用以下命令让你的合约策略运行起来: ```shell ./simple_grid_future.py ``` * 用以下命令让你的现货策略运行起来: ```shell ./simple_grid_kucoin.py ``` * Windows **在项目目录下**打开命令终端: ```shell cd simple-grid ``` * 用以下命令让你的合约策略运行起来: ```shell py simple_grid_future.py ``` * 用以下命令让你的现货策略运行起来: ```shell py simple_grid_kucoin.py ``` 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值