├── .gitignore ├── LICENSE ├── README.md ├── backtest ├── __init__.py ├── backtester │ ├── __init__.py │ ├── array_manager.py │ ├── broker.py │ ├── data.py │ └── strategy.py ├── bitmex_btc_usd_1min_data.csv ├── demo_strategy.py └── 回测框架说明.md ├── binance_api ├── 1559978820000.csv ├── 1560038820000.csv ├── 1560098820000.csv ├── 1560158820000.csv ├── 1560218820000.csv ├── 1560278820000.csv ├── 1560338820000.csv ├── 1560398820000.csv ├── binance.py └── cvs │ └── 1559978820000.csv ├── bybit ├── crawl_kline_data.py └── 交易所介绍.md ├── ccxt_future └── ccxt合约交易.md ├── ccxt_study ├── Test2.py ├── account.txt ├── ccxt02.py ├── ccxt_01.py └── 如何学习CCXT框架.md ├── code_software.md ├── crawl_exchanges_datas └── crawler.py ├── huobi_api └── huobi.py ├── learn-decimal.py ├── pandas_basic ├── binance_btc_1min.csv ├── pandas_basic1.py ├── pandas_basic2.py ├── pandas_read_muti_csv3.py └── pandas_resample_data4.py ├── python_abc ├── func.py ├── list_dict.py ├── loop.py └── str_and_num.py ├── technical_indicators ├── technical_indicators.md └── technical_indicators.py ├── wallet └── 钱包.md ├── weixinbot ├── AI公司代码.pic.jpg ├── wechat_orderbot.py └── weixinbot.py ├── 安装包说明.txt └── 币安智能链BSC之汉堡挖矿入门到精通.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.idea* 2 | ccxt-master 3 | */__pycache__ 4 | */*/__pycache__ 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ramoslin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python数字货币量化交易视频代码 2 | youtube视频链接: [https://www.youtube.com/channel/UCjCMoRi4dZ6LRV2KL_RP8KQ/videos](https://www.youtube.com/channel/UCjCMoRi4dZ6LRV2KL_RP8KQ/videos) 3 | 4 | B站找到视频链接: [https://space.bilibili.com/401686908](https://space.bilibili.com/401686908) 5 | 6 | ## 币安合约交易快速下单软件下载 7 | 链接地址:https://share.weiyun.com/F03qTiin 8 | 9 | # 网易云课堂进阶课程 10 | 如果你想学习进阶的课程,可以看下一网易云课堂的视频: https://study.163.com/course/courseMain.htm?courseId=1209509824 11 | 12 | 课程包含python基础知识, 网络请求REST API, Websocket, 回测、策略, 实盘交易,以及linux服务器都有讲解,目前课程已经更新完结。 13 | 你可以在网易云看下课程目录,非常的详细,适合入门和提高。具体可以网易云搜索51bitquant, 或者加我微信咨询:**bitquant51** 14 | 15 | # 马丁策略 16 | 1. 马丁策略可以基于howtrader进行开发, 具体策略可以参考: https://github.com/51bitquant/course_codes 下面的25/26/27课代码,相应的是视频可以参考网易云课堂的视频: https://study.163.com/course/courseMain.htm?courseId=1210904816 17 | 2. 另外多币种的马丁策略,强势币的马丁策略代码如下: https://github.com/51bitquant/multi_pairs_martingle_bot 18 | 19 | # 网格交易代码 20 | 21 | https://github.com/ramoslin02/binance_grid_trader 22 | 23 | 网格交易的原理视频讲解链接: 24 | [https://www.bilibili.com/video/BV1Jg4y1v7vr/](https://www.bilibili.com/video/BV1Jg4y1v7vr/) 25 | 26 | # 交易所注册推荐码 27 | 28 | - OKEX 交易所注册推荐码, 手续费返佣**20%** 29 | - [https://www.okex.me/join/1847111798](https://www.okex.me/join/1847111798) 30 | 31 | - 币安现货推荐码:返佣**20%** 32 | - [https://www.binancezh.com/cn/register?ref=ESE80ESH](https://www.binancezh.com/cn/register?ref=ESE80ESH) 33 | 34 | - 币安合约推荐码:返佣10% 35 | - [https://www.binancezh.com/cn/futures/ref/51bitquant](https://www.binancezh.com/cn/futures/ref/51bitquant) 36 | 37 | **如果你的交易手续费比较多,你可以联系我,给你提供返佣的定制服务。添加微信: bitquant51 *** 38 | 39 | #网格交易策略使用行情 40 | - 震荡行情 41 | - 适合币圈的高波动率的品种 42 | - 适合现货, 如果交易合约,需要注意防止极端行情爆仓。 43 | 44 | # 服务器购买 45 | 推荐ucloud的服务器 46 | - 价格便宜 47 | - 网络速度和性能还不错 48 | - 推荐链接如下:可以通过下面链接够买服务器,可以享受打折优惠: 49 | 50 | [https://www.ucloud.cn/site/active/kuaijie.html?invitation_code=C1x2EA81CD79B8C#dongjing](https://www.ucloud.cn/site/active/kuaijie.html?invitation_code=C1x2EA81CD79B8C#dongjing) 51 | 52 | 视频讲解如下: 53 | [https://www.bilibili.com/video/BV1eK4y147HT/](https://www.bilibili.com/video/BV1eK4y147HT/) 54 | 55 | 56 | # 部署服务器 57 | 参考我的博客 58 | - [https://www.jianshu.com/p/50fc54ca5ead](https://www.jianshu.com/p/50fc54ca5ead) 59 | - [https://www.jianshu.com/p/61cb2a24a658](https://www.jianshu.com/p/61cb2a24a658) 60 | - [https://www.jianshu.com/p/8c1afcbbe722](https://www.jianshu.com/p/8c1afcbbe722) 61 | 62 | 63 | # linux 常用命令 64 | 65 | - cd # 是切换工作目录, 具体使用可以通过man 指令 | 指令 --help 66 | - clear 67 | - ls # 列出当前文件夹的文件 68 | - rm 文件名 # 删除文件 69 | - rm -rf 文件夹 # 删除文件 70 | - cp # 拷贝文件 copy 71 | - scp scp binance_grid_trader.zip ubuntu@xxx.xxx.xxx.xxx:/home/ubuntu 72 | - pwd 73 | - mv # 移动或者剪切文件 74 | - ps -ef | grep main.py # 查看进程 75 | - kill 进程id # 杀死当前进程 76 | 77 | # 部署 78 | 直接把代码上传到服务器, 通过scp命令上传 79 | - 先把代码压缩一下 80 | - 通过一下命令上传到自己的服务器, **xxx.xxx.xxx.xxx**为你的服务器地址, **:/home/ubuntu**表示你上传到服务器的目录 81 | 82 | > scp binance_grid_trader.zip ubuntu@xxx.xxx.xxx.xxx:/home/ubuntu 83 | 84 | 安装软件 sudo apt-get install 软件名称 | 库 85 | > sudo apt-get install unzip # pip install requests 86 | 解压文件 87 | > unzip binance_grid_trader.zip 88 | 89 | 进入该文件夹目录 90 | > cd binance_grid_trader 91 | 92 | 安装依赖包 93 | > pip install -r requirements.txt 94 | 95 | 执行运行脚本 96 | > sh start.sh 97 | 98 | 查看程序运行的id 99 | > ps -ef | grep main.py 100 | 101 | 杀死进程, 关闭程序 102 | > kill <进程ID> 103 | 104 | **linux服务器指令和网格策略实盘部署过程如下** 105 | [https://www.bilibili.com/video/BV1mK411n7JW/](https://www.bilibili.com/video/BV1mK411n7JW/) 106 | 107 | 108 | # 更多课程内容 109 | 请参考网易云课堂的视频 110 | - [网易云课堂链接](https://www.jianshu.com/go-wild?ac=2&url=https%3A%2F%2Fstudy.163.com%2Fcourse%2FcourseMain.htm%3FcourseId%3D1209509824%26share%3D2%26shareId%3D480000001919830) 111 | - 你也可以在网易云课堂直接搜索**51bitquant**可以找到课程视频。 112 | # 联系我 113 | 可以添加我的微信,如果你有什么量化问题、python学习、课程咨询等方面的问题,都可以咨询我。 114 | 115 | ![51bitquant个人微信](https://upload-images.jianshu.io/upload_images/814550-f83c8302f2c4e344.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /backtest/__init__.py: -------------------------------------------------------------------------------- 1 | from .backtester import * -------------------------------------------------------------------------------- /backtest/backtester/__init__.py: -------------------------------------------------------------------------------- 1 | from .strategy import BaseStrategy 2 | from .broker import Broker 3 | from .data import BarData, TradeData 4 | from .array_manager import ArrayManager -------------------------------------------------------------------------------- /backtest/backtester/array_manager.py: -------------------------------------------------------------------------------- 1 | """ 2 | Broker 经济人,负责处理处理撮合交易订单等功能. 3 | 4 | 微信:bitquant51 5 | 火币交易所推荐码:asd43 6 | 币安推荐码: 22795115 7 | 币安推荐链接:https://www.binance.co/?ref=22795115 8 | Gateio交易所荐码:1100714 9 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 10 | 11 | 代码地址: https://github.com/ramoslin02/51bitqunt 12 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 13 | B站视频: 14 | 15 | """ 16 | 17 | import numpy as np 18 | import talib 19 | from .data import BarData 20 | 21 | class ArrayManager(object): 22 | """ 23 | For: 24 | 1. time series container of bar data 25 | 2. calculating technical indicator value 26 | """ 27 | 28 | def __init__(self, size=500): 29 | """Constructor""" 30 | self.count = 0 31 | self.size = size 32 | self.inited = False 33 | 34 | self.open_array = np.zeros(size) 35 | self.high_array = np.zeros(size) 36 | self.low_array = np.zeros(size) 37 | self.close_array = np.zeros(size) 38 | self.volume_array = np.zeros(size) 39 | 40 | def update_bar(self, bar: BarData): 41 | """ 42 | Update new bar data into array manager. 43 | """ 44 | self.count += 1 45 | if not self.inited and self.count >= self.size: 46 | self.inited = True 47 | 48 | # [1,2,3,4,5,6,7,8,9,10] 49 | # [1,2,3,4,5,6,7,8,9] = [2,3,4,5,6,7,8,9,10] 50 | # [2,3,4,5,6,7,8,9,10, 10] 51 | self.open_array[:-1] = self.open_array[1:] 52 | self.high_array[:-1] = self.high_array[1:] 53 | self.low_array[:-1] = self.low_array[1:] 54 | self.close_array[:-1] = self.close_array[1:] 55 | self.volume_array[:-1] = self.volume_array[1:] 56 | 57 | # [2,3,4,5,6,7,8,9,10, 10] 然后最后一个数字被替换了. 58 | self.open_array[-1] = bar.open_price 59 | self.high_array[-1] = bar.high_price 60 | self.low_array[-1] = bar.low_price 61 | self.close_array[-1] = bar.close_price 62 | self.volume_array[-1] = bar.volume 63 | 64 | @property 65 | def open(self): 66 | """ 67 | Get open price time series. 68 | """ 69 | return self.open_array 70 | 71 | @property 72 | def high(self): 73 | """ 74 | Get high price time series. 75 | """ 76 | return self.high_array 77 | 78 | @property 79 | def low(self): 80 | """ 81 | Get low price time series. 82 | """ 83 | return self.low_array 84 | 85 | @property 86 | def close(self): 87 | """ 88 | Get close price time series. 89 | """ 90 | return self.close_array 91 | 92 | @property 93 | def volume(self): 94 | """ 95 | Get trading volume time series. 96 | """ 97 | return self.volume_array 98 | 99 | def sma(self, n, array=False): 100 | """ 101 | Simple moving average. 102 | """ 103 | result = talib.SMA(self.close, n) 104 | if array: 105 | return result 106 | return result[-1] 107 | 108 | def std(self, n, array=False): 109 | """ 110 | Standard deviation 111 | """ 112 | result = talib.STDDEV(self.close, n) 113 | if array: 114 | return result 115 | return result[-1] 116 | 117 | def cci(self, n, array=False): 118 | """ 119 | Commodity Channel Index (CCI). 120 | """ 121 | result = talib.CCI(self.high, self.low, self.close, n) 122 | if array: 123 | return result 124 | return result[-1] 125 | 126 | def atr(self, n, array=False): 127 | """ 128 | Average True Range (ATR). 129 | """ 130 | result = talib.ATR(self.high, self.low, self.close, n) 131 | if array: 132 | return result 133 | return result[-1] 134 | 135 | def rsi(self, n, array=False): 136 | """ 137 | Relative Strenght Index (RSI). 138 | """ 139 | result = talib.RSI(self.close, n) 140 | if array: 141 | return result 142 | return result[-1] 143 | 144 | def macd(self, fast_period, slow_period, signal_period, array=False): 145 | """ 146 | MACD. 147 | """ 148 | macd, signal, hist = talib.MACD( 149 | self.close, fast_period, slow_period, signal_period 150 | ) 151 | if array: 152 | return macd, signal, hist 153 | return macd[-1], signal[-1], hist[-1] 154 | 155 | def adx(self, n, array=False): 156 | """ 157 | ADX. 158 | """ 159 | result = talib.ADX(self.high, self.low, self.close, n) 160 | if array: 161 | return result 162 | return result[-1] 163 | 164 | def boll(self, n, dev, array=False): 165 | """ 166 | Bollinger Channel. 167 | """ 168 | mid = self.sma(n, array) 169 | std = self.std(n, array) 170 | 171 | up = mid + std * dev 172 | down = mid - std * dev 173 | 174 | return up, down 175 | 176 | def keltner(self, n, dev, array=False): 177 | """ 178 | Keltner Channel. 179 | """ 180 | mid = self.sma(n, array) 181 | atr = self.atr(n, array) 182 | 183 | up = mid + atr * dev 184 | down = mid - atr * dev 185 | 186 | return up, down 187 | 188 | def donchian(self, n, array=False): 189 | """ 190 | Donchian Channel. 191 | """ 192 | up = talib.MAX(self.high, n) 193 | down = talib.MIN(self.low, n) 194 | 195 | if array: 196 | return up, down 197 | return up[-1], down[-1] 198 | -------------------------------------------------------------------------------- /backtest/backtester/broker.py: -------------------------------------------------------------------------------- 1 | """ 2 | Broker 经济人,负责处理处理撮合交易订单等功能. 3 | 4 | 微信:bitquant51 5 | 火币交易所推荐码:asd43 6 | 币安推荐码: 22795115 7 | 币安推荐链接:https://www.binance.co/?ref=22795115 8 | Gateio交易所荐码:1100714 9 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 10 | 11 | 代码地址: https://github.com/ramoslin02/51bitqunt 12 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 13 | B站视频:https://space.bilibili.com/401686908 14 | 15 | 16 | """ 17 | import os 18 | import itertools 19 | import numpy as np 20 | import pandas as pd 21 | import collections 22 | 23 | from .strategy import BaseStrategy, BarData 24 | 25 | 26 | class Broker(object): 27 | def __init__(self): 28 | super(Broker, self).__init__() 29 | 30 | # 策略实例. 31 | self.strategy_instance = None 32 | 33 | # 手续费 34 | self.commission = 2/1000 35 | 36 | # 杠杆的比例, 默认使用杠杆. 37 | self.leverage = 1.0 38 | 39 | # 滑点率,设置为万5 40 | self.slipper_rate = 5/10000 41 | 42 | # 购买的资产的估值,作为计算爆仓的时候使用. 43 | self.asset_value = 0 44 | 45 | # 最低保证金比例, 使用bitfinex 的为例子. 46 | self.min_margin_rate = 0.15 47 | 48 | # 初始本金. 49 | self.cash = 1_000_000 50 | 51 | self.strategy_class = None 52 | 53 | # 交易的数据. 54 | self.trades = [] 55 | 56 | # 当前提交的订单. 57 | self.active_orders = [] 58 | 59 | # 回测的数据 dataframe数据 60 | self.backtest_data = None 61 | 62 | self.pos = 0 # 当前的持仓量.. 63 | 64 | # 是否是运行策略优化的方法。 65 | self.is_optimizing_strategy = False 66 | 67 | 68 | def set_strategy(self, strategy_class:BaseStrategy): 69 | """ 70 | 设置要跑的策略类. 71 | :param strategy_class: 72 | :return: 73 | """ 74 | self.strategy_class = strategy_class 75 | 76 | def set_leverage(self, leverage: float): 77 | """ 78 | 设置杠杆率. 79 | :param leverage: 80 | :return: 81 | """ 82 | self.leverage = leverage 83 | 84 | def set_commission(self, commission: float): 85 | """ 86 | 设置手续费. 87 | :param commission: 88 | :return: 89 | """ 90 | self.commission = commission 91 | 92 | def set_backtest_data(self, data: pd.DataFrame): 93 | self.backtest_data = data 94 | 95 | def set_cash(self, cash): 96 | self.cash = cash 97 | 98 | def buy(self, price, volume): 99 | """ 100 | 这里生成订单. 101 | order需要包含的信息, order_id, order_price, volume, order_time. 102 | :param price: 103 | :param volume: 104 | :return: 105 | """ 106 | print(f"做多下单: {volume}@{price}") 107 | 108 | """ 109 | 在这里生成订单, 等待价格到达后成交. 110 | """ 111 | 112 | def sell(self, price, volume): 113 | print(f"做多平仓下单: {volume}@{price}") # 114 | """ 115 | 在这里生成订单, 等待价格到达后成交. 116 | """ 117 | 118 | def short(self, price, volume): 119 | print(f"做空下单: {volume}@{price}") 120 | """ 121 | 在这里生成订单, 等待价格到达后成交. 122 | """ 123 | 124 | def cover(self, price, volume): 125 | print(f"做空平仓下单: {volume}@{price}") 126 | """ 127 | 在这里生成订单, 等待价格到达后成交. 128 | """ 129 | 130 | def run(self): 131 | 132 | self.trades = [] # 开始策略前,把trades设置为空列表,表示没有任何交易记录. 133 | self.active_orders = [] # 134 | self.strategy_instance = self.strategy_class(self.backtest_data) 135 | self.strategy_instance.broker = self 136 | self.strategy_instance.on_start() 137 | 138 | 139 | for index, candle in self.backtest_data.iterrows(): 140 | bar = BarData(candle['open_time'], candle['open'], 141 | candle['high'], candle['low'], candle['close'], candle['volume']) 142 | 143 | self.check_order(bar) # 检查订单是否成交.. 144 | self.strategy_instance.next_bar(bar) # 处理数据.. 145 | 146 | self.strategy_instance.on_stop() 147 | 148 | 149 | # 统计成交的信息.. 夏普率、 盈亏比、胜率、 最大回撤 年化率/最大回撤 150 | self.calculate() # usdt. 151 | 152 | def calculate(self): 153 | 154 | # 拿到成交的信息,把成交的记录统计出来. 155 | 156 | for trade in self.trades: 157 | """ 158 | order_id 159 | trade_id 160 | price, 161 | volume 162 | 163 | 10000 --> 1BTC 164 | 12000 --> 1BTC -- > 2000 165 | """ 166 | pass 167 | 168 | def check_order(self, bar): 169 | """ 170 | 根据订单信息, 检查是否满足成交的价格, 然后生成交易的记录. 171 | :param bar: 172 | :return: 173 | """ 174 | """ 175 | 在这里比较比较订单的价格与当前价格是否满足成交,如果满足,在这里撮合订单。 176 | """ 177 | 178 | 179 | def optimize_strategy(self, **kwargs): 180 | """ 181 | 优化策略, 参数遍历进行.. 182 | :param kwargs: 183 | :return: 184 | """ 185 | self.is_optimizing_strategy = True 186 | 187 | optkeys = list(kwargs) 188 | vals = iterize(kwargs.values()) 189 | optvals = itertools.product(*vals) # 190 | optkwargs = map(zip, itertools.repeat(optkeys), optvals) 191 | optkwargs = map(dict, optkwargs) # dict value... 192 | 193 | for params in optkwargs: 194 | print(params) 195 | 196 | # 参数列表, 要优化的参数, 放在这里. 197 | 198 | cash = self.cash 199 | leverage = self.leverage 200 | commission = self.commission 201 | for params in optkwargs: 202 | 203 | self.strategy_class.params = params 204 | self.set_cash(cash) 205 | self.set_leverage(leverage) 206 | self.set_commission(commission) 207 | self.run() 208 | 209 | def iterize(iterable): 210 | '''Handy function which turns things into things that can be iterated upon 211 | including iterables 212 | ''' 213 | niterable = list() 214 | for elem in iterable: 215 | if isinstance(elem, str): 216 | elem = (elem,) 217 | elif not isinstance(elem, collections.Iterable): 218 | elem = (elem,) 219 | 220 | niterable.append(elem) 221 | 222 | return niterable -------------------------------------------------------------------------------- /backtest/backtester/data.py: -------------------------------------------------------------------------------- 1 | """ 2 | 测试用的 barData, 3 | 4 | 微信:bitquant51 5 | 火币交易所推荐码:asd43 6 | 币安推荐码: 22795115 7 | 币安推荐链接:https://www.binance.co/?ref=22795115 8 | Gateio交易所荐码:1100714 9 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 10 | 11 | 代码地址: https://github.com/ramoslin02/51bitqunt 12 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 13 | B站视频:https://space.bilibili.com/401686908 14 | """ 15 | 16 | 17 | class BarData(object): 18 | """ 19 | K 线数据模型. 20 | """ 21 | def __init__(self, datetime, open_price, high_price, low_price, close_price, volume): 22 | self.datetime = datetime 23 | self.open_price = open_price 24 | self.high_price = high_price 25 | self.low_price = low_price 26 | self.close_price = close_price 27 | self.volume = volume 28 | 29 | def __str__(self): 30 | return f"{self.datetime} {self.open_price} {self.high_price} {self.low_price} {self.close_price}" 31 | 32 | 33 | class TradeData(object): 34 | pass -------------------------------------------------------------------------------- /backtest/backtester/strategy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Base Strategy for CTA. 3 | 4 | 微信:bitquant51 5 | 火币交易所推荐码:asd43 6 | 币安推荐码: 22795115 7 | 币安推荐链接:https://www.binance.co/?ref=22795115 8 | Gateio交易所荐码:1100714 9 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 10 | 11 | 代码地址: https://github.com/ramoslin02/51bitqunt 12 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 13 | B站视频:https://space.bilibili.com/401686908 14 | """ 15 | import numpy as np 16 | import pandas as pd 17 | from .data import BarData 18 | 19 | __author__ = '51bitquant' # 作者. 20 | __wxchat__ = 'bitquant51' # 微信. 21 | 22 | 23 | 24 | class BaseStrategy(object): 25 | 26 | broker = None # 经纪人.. 27 | data = None 28 | 29 | def __init__(self, data: pd.DataFrame): 30 | super(BaseStrategy, self).__init__() 31 | self.data = data 32 | 33 | def on_start(self): 34 | """ 35 | 策略开始运行. 36 | :return: 37 | """ 38 | 39 | def on_stop(self): 40 | """ 41 | 策略运行结束. 42 | :return: 43 | """ 44 | 45 | def next_bar(self, bar: BarData): 46 | raise NotImplementedError("请在子类中实现该方法..") 47 | 48 | 49 | def buy(self, price, volume): 50 | """ 51 | 期货中做多,或者现货买 52 | :param price: 价格 53 | :param volume: 数量 54 | :return: 55 | """ 56 | self.broker.buy(price, volume) 57 | 58 | 59 | def sell(self, price, volume): 60 | """ 61 | 期货合约平多,现货中的卖 62 | :param price: 价格 63 | :param volume: 数量 64 | :return: 65 | """ 66 | self.broker.sell(price, volume) 67 | 68 | 69 | def short(self, price, volume): 70 | """ 71 | 期货做空, 72 | :param price: 价格 73 | :param volume: 数量 74 | :return: 75 | """ 76 | 77 | self.broker.short(price, volume) 78 | 79 | 80 | def cover(self, price, volume): 81 | """ 82 | 做空平仓, 83 | :param price: 价格 84 | :param volume: 数量 85 | :return: 86 | """ 87 | 88 | self.cover(price, volume) 89 | 90 | -------------------------------------------------------------------------------- /backtest/demo_strategy.py: -------------------------------------------------------------------------------- 1 | """ 2 | 微信:bitquant51 3 | 火币交易所推荐码:asd43 4 | 币安推荐码: 22795115 5 | 币安推荐链接:https://www.binance.co/?ref=22795115 6 | Gateio交易所荐码:1100714 7 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 8 | 9 | 代码地址: https://github.com/ramoslin02/51bitqunt 10 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 11 | B站视频更新:https://space.bilibili.com/401686908 12 | 13 | """ 14 | 15 | __author__ = "51bitquant" # 作者. 16 | __weixin__ = "bitquant51" # 微信. 17 | 18 | 19 | from backtest.backtester import Broker, BaseStrategy, BarData, ArrayManager 20 | import pandas as pd 21 | 22 | 23 | class DemoStrategy(BaseStrategy): 24 | 25 | params = {'long_period': 110, 'short_period': 70} # 26 | 27 | def __init__(self, data): 28 | super(DemoStrategy, self).__init__(data) 29 | self.am = ArrayManager(size=1000) # 计算产生的信号.. 30 | 31 | def on_start(self): 32 | print("策略开始运行..") 33 | 34 | def on_stop(self): 35 | print("策略停止运行..") 36 | 37 | def next_bar(self, bar: BarData): 38 | """ 39 | 这里是核心,整个策略都在这里实现.. 40 | :param bar: 41 | :return: 42 | """ 43 | print(bar) 44 | self.am.update_bar(bar) 45 | if not self.am.inited: 46 | return 47 | 48 | # 计算技术指标.. 产生交易新号.. 49 | # 或者合成不同周期的K线数据等. 50 | # 第一个数[-1] ---> [-2] 51 | 52 | if True: 53 | self.buy(bar.close_price, 1) 54 | else: 55 | self.sell(bar.close_price, 1) 56 | 57 | 58 | if __name__ == '__main__': 59 | 60 | 61 | df = pd.read_csv('bitmex_btc_usd_1min_data.csv') 62 | df = df[df['open_time'] >= '2019-01-01'] 63 | df = df[df['open_time'] <= '2019-02-01'] 64 | 65 | df.reset_index(inplace=True, drop=True) 66 | # print(df) 67 | 68 | broker = Broker() 69 | broker.set_strategy(DemoStrategy) 70 | broker.set_leverage(1.0) 71 | broker.set_cash(1_000_000) # 100万初始资金. 72 | broker.set_backtest_data(df) # 数据. 73 | broker.run() 74 | 75 | # 参数优化, 穷举法, 遗传算法。 76 | # broker.optimize_strategy(long_period=[i for i in range(100, 300, 10)], short_period=[i for i in range(50, 100, 5)]) 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /backtest/回测框架说明.md: -------------------------------------------------------------------------------- 1 | 2 | # 回测的原理 3 | 4 | ## 回测和回撤是不相同 5 | 6 | backtest 回测,后验. 7 | 1. 通过对历史数据的进行模拟实盘交易,通过类似把行情数据通过按照时间序列先后顺序来模拟实盘的交易环节 8 | 2. 不能100%模拟真实环境 9 | 10 | ## strategy 类 11 | 1. 把历史的行情数据不断的推送给到测了类 12 | 2. 策略类负责合成生成技术指标,产生交易的信号 13 | 3. 处理订单等情况. 14 | 4. 集成来自基类BaseStrategy 15 | 16 | 17 | ## broker类 18 | 1. 负责处理撮合订单, 19 | 2. 统计各种交易的数据,计算盈亏比,夏普比例等交易信息 20 | 3. 提供优化策略的方法 21 | 22 | 23 | -------------------------------------------------------------------------------- /binance_api/binance.py: -------------------------------------------------------------------------------- 1 | """ 2 | 微信:Griezmann_JR 3 | 火币交易所推荐码:asd43 4 | 币安推荐码: 22795115 5 | 币安推荐链接:https://www.binance.co/?ref=22795115 6 | Gateio交易所荐码:1100714 7 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 8 | 9 | 代码地址: https://github.com/ramoslin02/51bitqunt 10 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 11 | 12 | 1. bilibili.com 13 | 2. 优酷 youku.com 14 | 3. 百家号 baijiahao 15 | 4. 头条号 toutiao 16 | 5. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 17 | 18 | """ 19 | 20 | import requests 21 | import time 22 | import pandas as pd 23 | pd.set_option('expand_frame_repr', False) 24 | 25 | # BASE_URL = 'https://api.binance.com' 26 | # # 27 | # # kline = '/api/v1/klines' 28 | # # # 29 | # # kline_url = BASE_URL + kline + '?' + 'symbol=BTCUSDT&interval=1h&limit=1000' 30 | # # print(kline_url) 31 | # # resp = requests.get(kline_url) 32 | # # print(resp.json()) 33 | # # df = pd.DataFrame(resp.json()) 34 | # # print(df) 35 | # # exit() 36 | 37 | # 如何获取binance过去一年的数据. For While. 38 | 39 | 40 | BASE_URL = 'https://api.binance.com' 41 | limit = 1000 42 | end_time = int(time.time() // 60 * 60 * 1000) 43 | print(end_time) 44 | start_time = int(end_time - limit*60*1000) 45 | print(start_time) 46 | 47 | while True: 48 | 49 | url = BASE_URL + '/api/v1/klines' + '?symbol=BTCUSDT&interval=1m&limit=' + str(limit) + '&startTime=' + str( 50 | start_time) + '&endTime=' + str(end_time) 51 | print(url) 52 | resp = requests.get(url) 53 | data = resp.json() 54 | df = pd.DataFrame(data, columns={'open_time': 0, 'open': 1, 'high': 2, 'low': 3, 'close': 4, 'volume': 5, 55 | 'close_time': 6, 'quote_volume': 7, 'trades': 8, 'taker_base_volue': 9, 56 | 'taker_quote_volume': 10, 'ignore': 11}) 57 | 58 | df.set_index('open_time', inplace=True) 59 | df.to_csv(str(end_time) + '.csv') 60 | print(df) 61 | 62 | if len(df) < 1000: 63 | break 64 | 65 | end_time = start_time 66 | start_time = int(end_time - limit * 60 * 1000) 67 | -------------------------------------------------------------------------------- /bybit/crawl_kline_data.py: -------------------------------------------------------------------------------- 1 | """ 2 | 1. 注册链接: https://www.bybit.com/app/register?ref=yXjOz 3 | 推荐码:yXjOz, 目前官方有推荐返佣和奖励,以及各种活动奖励. 4 | 5 | 2. 官方网址:www.bybit.com, 注册需要科学上网,以后访问不需要. 6 | api文档: https://bybit-exchange.github.io/docs/zh-cn/inverse/#rest-api 7 | 8 | 3. 微信: 51bitquant, 网易云课程链接: https://study.163.com/course/introduction/1209509824.htm 9 | 或者网易云课堂(https://study.163.com)搜索: 51bitquant 10 | 4. 代码链接:https://github.com/ramoslin02/51bitqunt 11 | 12 | 5. 目标: 爬取Bybit交易所的行情数据, 对数据进行处理. 13 | 14 | 15 | """ 16 | 17 | import pandas as pd 18 | import time 19 | import os 20 | import datetime 21 | import ccxt 22 | 23 | pd.set_option('expand_frame_repr', False) 24 | 25 | 26 | def crawl_bybit_datas(symbol, start_time, end_time): 27 | """ 28 | 爬取交易所数据的方法. 29 | :param symbol: 请求的symbol: like BTC/USDT, ETH/USD等。 30 | :param start_time: like 2018-1-1 31 | :param end_time: like 2019-1-1 32 | :return: 33 | """ 34 | print(ccxt.__version__) # 1.18.1213 1.26.50 35 | # pip install ccxt==1.26.50 通过这个命令来安装最新的版本. 36 | # exchange_class = getattr(ccxt, 'bybit') # 获取交易所的名称 ccxt.binance 37 | # exchange = exchange_class() # 交易所的类. 类似 ccxt.bitfinex() 38 | exchange = ccxt.bybit() 39 | 40 | print(exchange) 41 | # exit() 42 | 43 | current_path = os.getcwd() 44 | file_dir = os.path.join(current_path, symbol.replace('/', '')) 45 | print(file_dir) 46 | if not os.path.exists(file_dir): 47 | # 如果这个文件路径不存在,则创建这个文件夹,来存放数据. 48 | os.makedirs(file_dir) 49 | 50 | start_time = datetime.datetime.strptime(start_time, '%Y-%m-%d') 51 | end_time = datetime.datetime.strptime(end_time, '%Y-%m-%d') 52 | 53 | start_time_stamp = int(time.mktime(start_time.timetuple())) * 1000 54 | end_time_stamp = int(time.mktime(end_time.timetuple())) * 1000 55 | 56 | limit_count = 200 # bybit 请求的数据有限制,每次只能请求200个. 57 | 58 | while True: 59 | try: 60 | print(start_time_stamp) 61 | data = exchange.fetch_ohlcv(symbol, timeframe='1m', since=start_time_stamp, limit=limit_count) 62 | df = pd.DataFrame(data) 63 | df.rename(columns={0: 'open_time', 1: 'open', 2: 'high', 3: 'low', 4: 'close', 5: 'volume'}, inplace=True) 64 | 65 | start_time_stamp = int(df.iloc[-1]['open_time']) # 获取下一个次请求的时间. 66 | filename = str(start_time_stamp) + '.csv' 67 | save_file_path = os.path.join(file_dir, filename) 68 | print("文件保存路径为:%s" % save_file_path) 69 | df.set_index('open_time', drop=True, inplace=True) 70 | df.to_csv(save_file_path) 71 | 72 | if start_time_stamp > end_time_stamp: 73 | print("完成数据的请求.") 74 | break 75 | 76 | time.sleep(0.2) # 1/25 77 | 78 | except Exception as error: 79 | print(error) 80 | time.sleep(10) 81 | 82 | 83 | def sample_datas(symbol): 84 | """ 85 | :param exchange_name: 86 | :param symbol: 87 | :return: 88 | """ 89 | path = os.path.join(os.getcwd(), symbol.replace('/', '')) 90 | print(path) 91 | file_paths = [] 92 | for root, dirs, files in os.walk(path): 93 | if files: 94 | for file in files: 95 | if file.endswith('.csv'): 96 | file_paths.append(os.path.join(path, file)) 97 | 98 | file_paths = sorted(file_paths) 99 | all_df = pd.DataFrame() 100 | 101 | for file in file_paths: 102 | df = pd.read_csv(file) 103 | all_df = all_df.append(df, ignore_index=True) 104 | 105 | all_df = all_df.sort_values(by='open_time', ascending=True) 106 | 107 | print(all_df) 108 | 109 | return all_df 110 | 111 | # for index, item in all_df.iterrows(): 112 | # try: 113 | # dt = (pd.to_datetime(item['open_time'], unit='ms')) 114 | # print(dt) 115 | # dt = datetime.datetime.strptime(str(dt), '%Y-%m-%d %H:%M:%S') # 2018-01-01 17:36:00:42 116 | # print(dt) 117 | # except: 118 | # dt = (pd.to_datetime(item['open_time'], unit='ms')) 119 | # print(dt) 120 | 121 | 122 | def clear_datas(symbol): 123 | df = sample_datas(symbol) 124 | # print(df) 125 | # exit() 126 | # df['open_time'] = df['open_time'].apply(lambda x: time.mktime(x.timetuple())) 127 | # # 日期.timetuple() 这个用法 通过它将日期转换成时间元组 128 | # # print(df) 129 | # df['open_time'] = df['open_time'].apply(lambda x: (x // 60) * 60 * 1000) 130 | df['open_time'] = df['open_time'].apply(lambda x: (x // 60) * 60) # 获取整分的数据. 131 | print(df) 132 | df['Datetime'] = pd.to_datetime(df['open_time'], unit='ms') + pd.Timedelta(hours=8) # 把UTC时间转成北京时间. 133 | df['Datetime'] = df['Datetime'].apply(lambda x: str(x)[0:19]) # 2018-11-15 00:47:0034, 通过截取字符串长度. 134 | df.drop_duplicates(subset=['open_time'], inplace=True) 135 | df.set_index('Datetime', inplace=True) 136 | print("*" * 20) 137 | print(df) 138 | symbol_path = symbol.replace('/', '') 139 | df.to_csv(f'{symbol_path}_1min_data.csv') 140 | 141 | 142 | if __name__ == '__main__': 143 | # crawl_bybit_datas('BTC/USD', '2018-11-15', '2020-4-18') # ccxt symbol BTC/USDT 144 | clear_datas('BTC/USD') 145 | -------------------------------------------------------------------------------- /bybit/交易所介绍.md: -------------------------------------------------------------------------------- 1 | # 关于bybit交易所 2 | 3 | 1. 注册链接: https://www.bybit.com/app/register?ref=yXjOz 4 | 推荐码:yXjOz, 目前官方有推荐返佣和奖励,以及各种活动奖励. 5 | 6 | 2. 官方网址:www.bybit.com, 注册需要科学上网,以后访问不需要. 7 | 8 | 3. bybit主要是期货/合约交易,目前没有现货交易对, 有USDT和BTC反向永续合约 9 | 交易所API相对很稳定,极端行情没有拔网线。 10 | 11 | 4. 吃单手续费0.075%, 吃单手续费 12 | -0.025%(相当于返佣), 参考链接: https://help.bybit.com/hc/zh-cn/articles/360039261154 13 | 14 | 5. API文档地址: https://bybit-exchange.github.io/docs/zh-cn/inverse/#t-introduction 15 | 16 | 6. 更多关于量化的视频,请看网易云课堂的视频: 网易云课程链接: https://study.163.com/course/introduction/1209509824.htm 17 | 或者在网易云课堂(https://study.163.com)搜索: 51bitquant -------------------------------------------------------------------------------- /ccxt_future/ccxt合约交易.md: -------------------------------------------------------------------------------- 1 | # CCXT 的使用. 2 | 3 | ## 初始化交易所 4 | 5 | 1. 简单初始化. 6 | ``` python 7 | xchange_id = 'binance' 8 | exchange_class = getattr(ccxt, exchange_id) 9 | exchange = exchange_class({ 10 | 'apiKey': 'YOUR_API_KEY', 11 | 'secret': 'YOUR_SECRET', 12 | 'timeout': 30000, 13 | 'enableRateLimit': True, 14 | }) 15 | 16 | ``` 17 | 2. 修改交易所的属性 18 | 19 | ``` 20 | # Python 21 | exchange = ccxt.binance ({ 22 | 'rateLimit': 10000, # unified exchange property 23 | 'headers': { 24 | 'YOUR_CUSTOM_HTTP_HEADER': 'YOUR_CUSTOM_VALUE', 25 | }, 26 | 'options': { 27 | 'adjustForTimeDifference': True, # exchange-specific option 28 | } 29 | }) 30 | exchange.options['adjustForTimeDifference'] = False 31 | ``` 32 | 33 | 34 | ## 交易所类的结构. 35 | 每一个交易所都有一系列的属性和方法,大部分的属性你都可以在初始化的时候,通过传递相关的数组属性去修改。 36 | 你也可以通过集成该类然后去修改它。 37 | 38 | 交易所的基类的属性如下: 39 | 40 | ``` 41 | { 42 | 'id': 'exchange' // lowercase string exchange id 43 | 'name': 'Exchange' // human-readable string 44 | 'countries': [ 'US', 'CN', 'EU' ], // array of ISO country codes 45 | 'urls': { 46 | 'api': 'https://api.example.com/data', // string or dictionary of base API URLs 47 | 'www': 'https://www.example.com' // string website URL 48 | 'doc': 'https://docs.example.com/api', // string URL or array of URLs 49 | }, 50 | 'version': 'v1', // string ending with digits 51 | 'api': { ... }, // dictionary of api endpoints 52 | 'has': { // exchange capabilities 53 | 'CORS': false, 54 | 'publicAPI': true, 55 | 'privateAPI': true, 56 | 'cancelOrder': true, 57 | 'createDepositAddress': false, 58 | 'createOrder': true, 59 | 'deposit': false, 60 | 'fetchBalance': true, 61 | 'fetchClosedOrders': false, 62 | 'fetchCurrencies': false, 63 | 'fetchDepositAddress': false, 64 | 'fetchMarkets': true, 65 | 'fetchMyTrades': false, 66 | 'fetchOHLCV': false, 67 | 'fetchOpenOrders': false, 68 | 'fetchOrder': false, 69 | 'fetchOrderBook': true, 70 | 'fetchOrders': false, 71 | 'fetchStatus': 'emulated', 72 | 'fetchTicker': true, 73 | 'fetchTickers': false, 74 | 'fetchBidsAsks': false, 75 | 'fetchTrades': true, 76 | 'withdraw': false, 77 | }, 78 | 'timeframes': { // empty if the exchange.has['fetchOHLCV'] !== true 79 | '1m': '1minute', 80 | '1h': '1hour', 81 | '1d': '1day', 82 | '1M': '1month', 83 | '1y': '1year', 84 | }, 85 | 'timeout': 10000, // number in milliseconds 86 | 'rateLimit': 2000, // number in milliseconds 87 | 'userAgent': 'ccxt/1.1.1 ...' // string, HTTP User-Agent header 88 | 'verbose': false, // boolean, output error details 89 | 'markets': { ... } // dictionary of markets/pairs by symbol 90 | 'symbols': [ ... ] // sorted list of string symbols (traded pairs) 91 | 'currencies': { ... } // dictionary of currencies by currency code 92 | 'markets_by_id': { ... }, // dictionary of dictionaries (markets) by id 93 | 'proxy': 'https://crossorigin.me/', // string URL 94 | 'apiKey': '92560ffae9b8a0421...', // string public apiKey (ASCII, hex, Base64, ...) 95 | 'secret': '9aHjPmW+EtRRKN/Oi...' // string private secret key 96 | 'password': '6kszf4aci8r', // string password 97 | 'uid': '123456', // string user id 98 | } 99 | 100 | ``` 101 | 102 | -------------------------------------------------------------------------------- /ccxt_study/Test2.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/51bitquant/bitquant/a19e703238a7d4c06240a0aa3d31699ad8a7e68f/ccxt_study/Test2.py -------------------------------------------------------------------------------- /ccxt_study/account.txt: -------------------------------------------------------------------------------- 1 | ht4tgq1e4t-5a020fae-30e16567-d34; 2 | 23f36060-ee65ff37-c5e2c457-ec7; -------------------------------------------------------------------------------- /ccxt_study/ccxt02.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | 微信:bitquant51 4 | 火币交易所推荐码:asd43 5 | 币安推荐码: 22795115 6 | 币安推荐链接:https://www.binance.co/?ref=22795115 7 | Gateio交易所荐码:1100714 8 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 9 | 10 | github代码地址: https://github.com/ramoslin02/51bitqunt 11 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 12 | 13 | 0. Youtube: https://www.youtube.com/channel/UCjCMoRi4dZ6LRV2KL_RP8KQ/videos 14 | 1. bilibili.com 51bitquant 15 | 2. 爱奇艺:https://www.iqiyi.com/u/1752521752 16 | 17 | """ 18 | import ccxt 19 | # 获取私有api 20 | apiKey = '换成你的apiKey' 21 | secret = '请换成你的secret' 22 | binance = ccxt.binance({"apiKey": apiKey, 'secret': secret}) 23 | 24 | # 如何设置代理. 25 | # binance.proxies = { 26 | # 'http': 'http://10.10.1.10:3128', # these proxies won't work for you, they are here for example 27 | # 'https': 'https://10.10.1.10:1080', 28 | # } 29 | 30 | # balance = binance.fetch_balance() # 账户的资金情况 31 | # print(balance) 32 | # print(balance['BNB']) 33 | # print(balance['ETH']) 34 | # exit() 35 | balance = """{'info': 36 | {'makerCommission': 10, 37 | 'takerCommission': 10, 38 | 'buyerCommission': 0, 39 | 'sellerCommission': 0, 40 | 'canTrade': True, 41 | 'canWithdraw': True, 42 | 'canDeposit': True, 43 | 'updateTime': 1562418686043, 44 | 'accountType': 'MARGIN', 45 | 'balances': [{'asset': 'BTC', 'free': '0.00000000', 'locked': '0.00000000'}, 46 | {'asset': 'LTC', 'free': '0.00000000', 'locked': '0.00000000'}, 47 | {'asset': 'ETH', 'free': '0.00000000', 'locked': '0.00000000'}, 48 | {'asset': 'NEO', 'free': '0.00000000', 'locked': '0.00000000'}, 49 | {'asset': 'BNB', 'free': '4.56050497', 'locked': '0.00000000'}, 50 | {'asset': 'QTUM', 'free': '0.00000000', 'locked': '0.00000000'}, 51 | {'asset': 'EOS', 'free': '0.00000000', 'locked': '0.00000000'}, 52 | {'asset': 'SNT', 'free': '0.00000000', 'locked': '0.00000000'}, 53 | {'asset': 'BNT', 'free': '0.00000000', 'locked': '0.00000000'}, 54 | {'asset': 'GAS', 'free': '0.00000000', 'locked': '0.00000000'}, 55 | {'asset': 'BCC', 'free': '0.00000000', 'locked': '0.00000000'}, 56 | {'asset': 'USDT', 'free': '0.00000000', 'locked': '0.00000000'}, 57 | {'asset': 'HSR', 'free': '0.00000000', 'locked': '0.00000000'}, 58 | {'asset': 'OAX', 'free': '0.00000000', 'locked': '0.00000000'}, 59 | {'asset': 'DNT', 'free': '0.00000000', 'locked': '0.00000000'}, 60 | {'asset': 'MCO', 'free': '0.00000000', 'locked': '0.00000000'}, 61 | {'asset': 'ICN', 'free': '0.00000000', 'locked': '0.00000000'}, 62 | {'asset': 'ZRX', 'free': '0.00000000', 'locked': '0.00000000'}, 63 | {'asset': 'OMG', 'free': '0.00000000', 'locked': '0.00000000'}, 64 | {'asset': 'WTC', 'free': '0.00000000', 'locked': '0.00000000'}, 65 | {'asset': 'YOYO', 'free': '0.00000000', 'locked': '0.00000000'}, 66 | {'asset': 'LRC', 'free': '0.00000000', 'locked': '0.00000000'}, 67 | {'asset': 'TRX', 'free': '0.00000000', 'locked': '0.00000000'}, 68 | {'asset': 'SNGLS', 'free': '0.00000000', 'locked': '0.00000000'}, 69 | {'asset': 'STRAT', 'free': '0.00000000', 'locked': '0.00000000'}, 70 | {'asset': 'BQX', 'free': '0.00000000', 'locked': '0.00000000'}, 71 | {'asset': 'FUN', 'free': '0.00000000', 'locked': '0.00000000'}, 72 | {'asset': 'KNC', 'free': '0.00000000', 'locked': '0.00000000'}, 73 | {'asset': 'CDT', 'free': '0.00000000', 'locked': '0.00000000'}, 74 | {'asset': 'XVG', 'free': '0.00000000', 'locked': '0.00000000'}, 75 | {'asset': 'IOTA', 'free': '0.00000000', 'locked': '0.00000000'}, 76 | {'asset': 'SNM', 'free': '0.00000000', 'locked': '0.00000000'}, 77 | {'asset': 'LINK', 'free': '0.00000000', 'locked': '0.00000000'}, 78 | {'asset': 'CVC', 'free': '0.00000000', 'locked': '0.00000000'}, 79 | {'asset': 'TNT', 'free': '0.00000000', 'locked': '0.00000000'}, 80 | {'asset': 'REP', 'free': '0.00000000', 'locked': '0.00000000'}, 81 | {'asset': 'MDA', 'free': '0.00000000', 'locked': '0.00000000'}, 82 | {'asset': 'DOGE', 'free': '0.00000000', 'locked': '0.00000000'}]}, 83 | 'BTC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 84 | 'LTC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 85 | 'ETH': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 86 | 'NEO': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 87 | 'BNB': {'free': 4.56050497, 'used': 0.0, 'total': 4.56050497}, 88 | 'QTUM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 89 | 'EOS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 90 | 'SNT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 91 | 'BNT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 92 | 'GAS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 93 | 'BCC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 94 | 'USDT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 95 | 'MTH': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 96 | 'ADX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 97 | 'ETC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ENG': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ZEC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'AST': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'GNT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DGD': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BAT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DASH': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'POWR': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BTG': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'REQ': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'XMR': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'EVX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'VIB': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ENJ': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'VEN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ARK': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'XRP': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'MOD': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'STORJ': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'KMD': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'RCN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'EDO': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DATA': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DLT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'MANA': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'PPT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'RDN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'GXS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'AMB': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ARN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BCPT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'CND': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'GVT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'POE': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BTS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'FUEL': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'XZC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'QSP': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'LSK': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BCD': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'TNB': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ADA': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'LEND': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'XLM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'CMT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'WAVES': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'WABI': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'GTO': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ICX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'OST': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ELF': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'AION': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'WINGS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BRD': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'NEBL': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'NAV': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'VIBE': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'LUN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'TRIG': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'APPC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'CHAT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'RLC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'INS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'PIVX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'IOST': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'STEEM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'NANO': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'AE': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'VIA': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BLZ': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'SYS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'RPX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'NCASH': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'POA': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ONT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ZIL': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'STORM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'XEM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'WAN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'WPR': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'QLC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'GRS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'CLOAK': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'LOOM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BCN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'TUSD': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ZEN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'SKY': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'THETA': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'IOTX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'QKC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'AGI': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'NXS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'SC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'NPXS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'KEY': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'NAS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'MFT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DENT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ARDR': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'HOT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'VET': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DOCK': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'POLY': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'VTHO': {'free': 2063.904624, 'used': 0.0, 'total': 2063.904624}, 'ONG': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'PHX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'HC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'GO': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'PAX': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'RVN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DCR': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'USDC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'MITH': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BCH': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BSV': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'REN': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BTT': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'USDS': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'FET': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'TFUEL': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'CELR': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'MATIC': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ATOM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'PHB': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ONE': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'FTM': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'BTCB': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'USDSB': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ALGO': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'ERD': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'DOGE': {'free': 0.0, 'used': 0.0, 'total': 0.0}, 'free': {'BTC': 0.0, 'LTC': 0.0, 'ETH': 0.0, 'NEO': 0.0, 'BNB': 4.56050497, 'QTUM': 0.0, 'EOS': 0.0, 'SNT': 0.0, 'BNT': 0.0, 'GAS': 0.0, 'BCC': 0.0, 'USDT': 0.0, 'HSR': 0.0, 'OAX': 0.0, 'DNT': 0.0, 'MCO': 0.0, 'ICN': 0.0, 'ZRX': 0.0, 'OMG': 0.0, 'WTC': 0.0, 'YOYOW': 0.0, 'LRC': 0.0, 'TRX': 0.0, 'SNGLS': 0.0, 'STRAT': 0.0, 'BQX': 0.0, 'FUN': 0.0, 'KNC': 0.0, 'CDT': 0.0, 'XVG': 0.0, 'IOTA': 0.0, 'SNM': 0.0, 'LINK': 0.0, 'CVC': 0.0, 'TNT': 0.0, 'REP': 0.0, 'MDA': 0.0, 'MTL': 0.0, 'SALT': 0.0, 'NULS': 0.0, 'SUB': 0.0, 'MTH': 0.0, 'ADX': 0.0, 'ETC': 0.0, 'ENG': 0.0, 'ZEC': 0.0, 'AST': 0.0, 'GNT': 0.0, 'DGD': 0.0, 'BAT': 0.0, 'DASH': 0.0, 'POWR': 0.0, 'BTG': 0.0, 'REQ': 0.0, 'XMR': 0.0, 'EVX': 0.0, 'VIB': 0.0, 'ENJ': 0.0, 'VEN': 0.0, 'ARK': 0.0, 'XRP': 0.0, 'MOD': 0.0, 'STORJ': 0.0, 'KMD': 0.0, 'RCN': 0.0, 'EDO': 0.0, 'DATA': 0.0, 'DLT': 0.0, 'MANA': 0.0, 'PPT': 0.0, 'RDN': 0.0, 'GXS': 0.0, 'AMB': 0.0, 'ARN': 0.0, 'BCPT': 0.0, 'CND': 0.0, 'GVT': 0.0, 'POE': 0.0, 'BTS': 0.0, 'FUEL': 0.0, 'XZC': 0.0, 'QSP': 0.0, 'LSK': 0.0, 'BCD': 0.0, 'TNB': 0.0, 'ADA': 0.0, 'LEND': 0.0, 'XLM': 0.0, 'CMT': 0.0, 'WAVES': 0.0, 'WABI': 0.0, 'GTO': 0.0, 'ICX': 0.0, 'OST': 0.0, 'ELF': 0.0, 'AION': 0.0, 'WINGS': 0.0, 'BRD': 0.0, 'NEBL': 0.0, 'NAV': 0.0, 'VIBE': 0.0, 'LUN': 0.0, 'TRIG': 0.0, 'APPC': 0.0, 'CHAT': 0.0, 'RLC': 0.0, 'INS': 0.0, 'PIVX': 0.0, 'IOST': 0.0, 'STEEM': 0.0, 'NANO': 0.0, 'AE': 0.0, 'VIA': 0.0, 'BLZ': 0.0, 'SYS': 0.0, 'RPX': 0.0, 'NCASH': 0.0, 'POA': 0.0, 'ONT': 0.0, 'ZIL': 0.0, 'STORM': 0.0, 'XEM': 0.0, 'WAN': 0.0, 'WPR': 0.0, 'QLC': 0.0, 'GRS': 0.0, 'CLOAK': 0.0, 'LOOM': 0.0, 'BCN': 0.0, 'TUSD': 0.0, 'ZEN': 0.0, 'SKY': 0.0, 'THETA': 0.0, 'IOTX': 0.0, 'QKC': 0.0, 'AGI': 0.0, 'NXS': 0.0, 'SC': 0.0, 'NPXS': 0.0, 'KEY': 0.0, 'NAS': 0.0, 'MFT': 0.0, 'DENT': 0.0, 'ARDR': 0.0, 'HOT': 0.0, 'VET': 0.0, 'DOCK': 0.0, 'POLY': 0.0, 'VTHO': 2063.904624, 'ONG': 0.0, 'PHX': 0.0, 'HC': 0.0, 'GO': 0.0, 'PAX': 0.0, 'RVN': 0.0, 'DCR': 0.0, 'USDC': 0.0, 'MITH': 0.0, 'BCH': 0.0, 'BSV': 0.0, 'REN': 0.0, 'BTT': 0.0, 'USDS': 0.0, 'FET': 0.0, 'TFUEL': 0.0, 'CELR': 0.0, 'MATIC': 0.0, 'ATOM': 0.0, 'PHB': 0.0, 'ONE': 0.0, 'FTM': 0.0, 'BTCB': 0.0, 'USDSB': 0.0, 'ALGO': 0.0, 'ERD': 0.0, 'DOGE': 0.0}, 'used': {'BTC': 0.0, 'LTC': 0.0, 'ETH': 0.0, 'NEO': 0.0, 'BNB': 0.0, 'QTUM': 0.0, 'EOS': 0.0, 'SNT': 0.0, 'BNT': 0.0, 'GAS': 0.0, 'BCC': 0.0, 'USDT': 0.0, 'HSR': 0.0, 'OAX': 0.0, 'DNT': 0.0, 'MCO': 0.0, 'ICN': 0.0, 'ZRX': 0.0, 'OMG': 0.0, 'WTC': 0.0, 'YOYOW': 0.0, 'LRC': 0.0, 'TRX': 0.0, 'SNGLS': 0.0, 'STRAT': 0.0, 'BQX': 0.0, 'FUN': 0.0, 'KNC': 0.0, 'CDT': 0.0, 'XVG': 0.0, 'IOTA': 0.0, 'SNM': 0.0, 'LINK': 0.0, 'CVC': 0.0, 'TNT': 0.0, 'REP': 0.0, 'MDA': 0.0, 'MTL': 0.0, 'SALT': 0.0, 'NULS': 0.0, 'SUB': 0.0, 'MTH': 0.0, 'ADX': 0.0, 'ETC': 0.0, 'ENG': 0.0, 'ZEC': 0.0, 'AST': 0.0, 'GNT': 0.0, 'DGD': 0.0, 'BAT': 0.0, 'DASH': 0.0, 'POWR': 0.0, 'BTG': 0.0, 'REQ': 0.0, 'XMR': 0.0, 'EVX': 0.0, 'VIB': 0.0, 'ENJ': 0.0, 'VEN': 0.0, 'ARK': 0.0, 'XRP': 0.0, 'MOD': 0.0, 'STORJ': 0.0, 'KMD': 0.0, 'RCN': 0.0, 'EDO': 0.0, 'DATA': 0.0, 'DLT': 0.0, 'MANA': 0.0, 'PPT': 0.0, 'RDN': 0.0, 'GXS': 0.0, 'AMB': 0.0, 'ARN': 0.0, 'BCPT': 0.0, 'CND': 0.0, 'GVT': 0.0, 'POE': 0.0, 'BTS': 0.0, 'FUEL': 0.0, 'XZC': 0.0, 'QSP': 0.0, 'LSK': 0.0, 'BCD': 0.0, 'TNB': 0.0, 'ADA': 0.0, 'LEND': 0.0, 'XLM': 0.0, 'CMT': 0.0, 'WAVES': 0.0, 'WABI': 0.0, 'GTO': 0.0, 'ICX': 0.0, 'OST': 0.0, 'ELF': 0.0, 'AION': 0.0, 'WINGS': 0.0, 'BRD': 0.0, 'NEBL': 0.0, 'NAV': 0.0, 'VIBE': 0.0, 'LUN': 0.0, 'TRIG': 0.0, 'APPC': 0.0, 'CHAT': 0.0, 'RLC': 0.0, 'INS': 0.0, 'PIVX': 0.0, 'IOST': 0.0, 'STEEM': 0.0, 'NANO': 0.0, 'AE': 0.0, 'VIA': 0.0, 'BLZ': 0.0, 'SYS': 0.0, 'RPX': 0.0, 'NCASH': 0.0, 'POA': 0.0, 'ONT': 0.0, 'ZIL': 0.0, 'STORM': 0.0, 'XEM': 0.0, 'WAN': 0.0, 'WPR': 0.0, 'QLC': 0.0, 'GRS': 0.0, 'CLOAK': 0.0, 'LOOM': 0.0, 'BCN': 0.0, 'TUSD': 0.0, 'ZEN': 0.0, 'SKY': 0.0, 'THETA': 0.0, 'IOTX': 0.0, 'QKC': 0.0, 'AGI': 0.0, 'NXS': 0.0, 'SC': 0.0, 'NPXS': 0.0, 'KEY': 0.0, 'NAS': 0.0, 'MFT': 0.0, 'DENT': 0.0, 'ARDR': 0.0, 'HOT': 0.0, 'VET': 0.0, 'DOCK': 0.0, 'POLY': 0.0, 'VTHO': 0.0, 'ONG': 0.0, 'PHX': 0.0, 'HC': 0.0, 'GO': 0.0, 'PAX': 0.0, 'RVN': 0.0, 'DCR': 0.0, 'USDC': 0.0, 'MITH': 0.0, 'BCH': 0.0, 'BSV': 0.0, 'REN': 0.0, 'BTT': 0.0, 'USDS': 0.0, 'FET': 0.0, 'TFUEL': 0.0, 'CELR': 0.0, 'MATIC': 0.0, 'ATOM': 0.0, 'PHB': 0.0, 'ONE': 0.0, 'FTM': 0.0, 'BTCB': 0.0, 'USDSB': 0.0, 'ALGO': 0.0, 'ERD': 0.0, 'DOGE': 0.0}, 'total': {'BTC': 0.0, 'LTC': 0.0, 'ETH': 0.0, 'NEO': 0.0, 'BNB': 4.56050497, 'QTUM': 0.0, 'EOS': 0.0, 'SNT': 0.0, 'BNT': 0.0, 'GAS': 0.0, 'BCC': 0.0, 'USDT': 0.0, 'HSR': 0.0, 'OAX': 0.0, 'DNT': 0.0, 'MCO': 0.0, 'ICN': 0.0, 'ZRX': 0.0, 'OMG': 0.0, 'WTC': 0.0, 'YOYOW': 0.0, 'LRC': 0.0, 'TRX': 0.0, 'SNGLS': 0.0, 'STRAT': 0.0, 'BQX': 0.0, 'FUN': 0.0, 'KNC': 0.0, 'CDT': 0.0, 'XVG': 0.0, 'IOTA': 0.0, 'SNM': 0.0, 'LINK': 0.0, 'CVC': 0.0, 'TNT': 0.0, 'REP': 0.0, 'MDA': 0.0, 'MTL': 0.0, 'SALT': 0.0, 'NULS': 0.0, 'SUB': 0.0, 'MTH': 0.0, 'ADX': 0.0, 'ETC': 0.0, 'ENG': 0.0, 'ZEC': 0.0, 'AST': 0.0, 'GNT': 0.0, 'DGD': 0.0, 'BAT': 0.0, 'DASH': 0.0, 'POWR': 0.0, 'BTG': 0.0, 'REQ': 0.0, 'XMR': 0.0, 'EVX': 0.0, 'VIB': 0.0, 'ENJ': 0.0, 'VEN': 0.0, 'ARK': 0.0, 'XRP': 0.0, 'MOD': 0.0, 'STORJ': 0.0, 'KMD': 0.0, 'RCN': 0.0, 'EDO': 0.0, 'DATA': 0.0, 'DLT': 0.0, 'MANA': 0.0, 'PPT': 0.0, 'RDN': 0.0, 'GXS': 0.0, 'AMB': 0.0, 'ARN': 0.0, 'BCPT': 0.0, 'CND': 0.0, 'GVT': 0.0, 'POE': 0.0, 'BTS': 0.0, 'FUEL': 0.0, 'XZC': 0.0, 'QSP': 0.0, 'LSK': 0.0, 'BCD': 0.0, 'TNB': 0.0, 'ADA': 0.0, 'LEND': 0.0, 'XLM': 0.0, 'CMT': 0.0, 'WAVES': 0.0, 'WABI': 0.0, 'GTO': 0.0, 'ICX': 0.0, 'OST': 0.0, 'ELF': 0.0, 'AION': 0.0, 'WINGS': 0.0, 'BRD': 0.0, 'NEBL': 0.0, 'NAV': 0.0, 'VIBE': 0.0, 'LUN': 0.0, 'TRIG': 0.0, 'APPC': 0.0, 'CHAT': 0.0, 'RLC': 0.0, 'INS': 0.0, 'PIVX': 0.0, 'IOST': 0.0, 'STEEM': 0.0, 'NANO': 0.0, 'AE': 0.0, 'VIA': 0.0, 'BLZ': 0.0, 'SYS': 0.0, 'RPX': 0.0, 'NCASH': 0.0, 'POA': 0.0, 'ONT': 0.0, 'ZIL': 0.0, 'STORM': 0.0, 'XEM': 0.0, 'WAN': 0.0, 'WPR': 0.0, 'QLC': 0.0, 'GRS': 0.0, 'CLOAK': 0.0, 'LOOM': 0.0, 'BCN': 0.0, 'TUSD': 0.0, 'ZEN': 0.0, 'SKY': 0.0, 'THETA': 0.0, 'IOTX': 0.0, 'QKC': 0.0, 'AGI': 0.0, 'NXS': 0.0, 'SC': 0.0, 'NPXS': 0.0, 'KEY': 0.0, 'NAS': 0.0, 'MFT': 0.0, 'DENT': 0.0, 'ARDR': 0.0, 'HOT': 0.0, 'VET': 0.0, 'DOCK': 0.0, 'POLY': 0.0, 'VTHO': 2063.904624, 'ONG': 0.0, 'PHX': 0.0, 'HC': 0.0, 'GO': 0.0, 'PAX': 0.0, 'RVN': 0.0, 'DCR': 0.0, 'USDC': 0.0, 'MITH': 0.0, 'BCH': 0.0, 'BSV': 0.0, 'REN': 0.0, 'BTT': 0.0, 'USDS': 0.0, 'FET': 0.0, 'TFUEL': 0.0, 'CELR': 0.0, 'MATIC': 0.0, 'ATOM': 0.0, 'PHB': 0.0, 'ONE': 0.0, 'FTM': 0.0, 'BTCB': 0.0, 'USDSB': 0.0, 'ALGO': 0.0, 'ERD': 0.0, 'DOGE': 0.0}}""" 98 | 99 | # orders = binance.fetch_orders('BNB/BTC') 100 | # print(len(orders)) 101 | # print(orders) 102 | # print('order_id: ' + str(orders[0]['id'])) 103 | # print('order_price: ' + str(orders[0]['price'])) 104 | # print('order_amount: ' + str(orders[0]['amount'])) 105 | # 106 | # print('orderId: ' + str(orders[0]['info']['orderId'])) 107 | # exit() 108 | 109 | 110 | # 创建订单. create_order(self, symbol, type, side, amount, price=None, params={}) buy 111 | # new_order = binance.create_order(symbol='BNB/BTC', type='limit', side='sell', amount=0.85, price=0.0030952) 112 | # print(new_order['info']['orderId']) # 216136323 113 | # exit() 114 | 115 | # 取消订单 116 | """ 117 | {'info': {'symbol': 'BNBBTC', 'orderId': 216112047, 'clientOrderId': 'mSKVC90FodJu3VLnBEjgHF', 'transactTime': 1562421786483, 'price': '0.00309520', 'origQty': '0.85000000', 'executedQty': '0.00000000', 'cummulativeQuoteQty': '0.00000000', 'status': 'NEW', 'timeInForce': 'GTC', 'type': 'LIMIT', 'side': 'SELL'}, 'id': '216112047', 'timestamp': 1562421786483, 'datetime': '2019-07-06T14:03:06.483Z', 'lastTradeTimestamp': None, 'symbol': 'BNB/BTC', 'type': 'limit', 'side': 'sell', 'price': 0.0030952, 'amount': 0.85, 'cost': 0.0, 'average': None, 'filled': 0.0, 'remaining': 0.85, 'status': 'open', 'fee': None, 'trades': None} 118 | """ 119 | # delete_order = binance.cancel_order(id='216136323', symbol='BNB/BTC') 120 | # print(delete_order) 121 | 122 | # 获取open_orders 123 | # open_orders = binance.fetch_open_orders('BNB/BTC') 124 | # print(open_orders) 125 | 126 | """ 127 | [{'info': {'symbol': 'BNBBTC', 'orderId': 133982998, 'clientOrderId': 'and_e59df70e20f4479fb8284724e6808a82', 128 | 'price': '0.00422410', 'origQty': '78.77000000', 'executedQty': '78.77000000', 'cummulativeQuoteQty': '0.33273235', 129 | 'status': 'FILLED', 'timeInForce': 'GTC', 'type': 'LIMIT', 'side': 'BUY', 'stopPrice': '0.00000000', 'icebergQty': '0.00000000', 130 | 'time': 1554104060825, 'updateTime': 1554104085528, 'isWorking': True}, 131 | 'id': '133982998', 'timestamp': 1554104060825, 'datetime': '2019-04-01T07:34:20.825Z', 'lastTradeTimestamp': None, 'symbol': 'BNB/BTC', 'type': 'limit', 132 | 'side': 'buy', 'price': 0.0042241, 'amount': 78.77, 'cost': 0.33273235, 'average': 0.004224099911133681, 133 | 'filled': 78.77, 'remaining': 0.0, 'status': 'closed', 'fee': None, 'trades': None}, 134 | {'info': {'symbol': 'BNBBTC', 'orderId': 216106130, 'clientOrderId': 'web_506bb43a60ea4ea89701d3a3a0f4b2b8', 'price': '0.00309520', 'origQty': '1.14000000', 'executedQty': '0.00000000', 'cummulativeQuoteQty': '0.00000000', 'status': 'NEW', 'timeInForce': 'GTC', 'type': 'LIMIT', 'side': 'SELL', 'stopPrice': '0.00000000', 'icebergQty': '0.00000000', 'time': 1562420837356, 'updateTime': 1562420837356, 'isWorking': True}, 135 | 'id': '216106130', 'timestamp': 1562420837356, 'datetime': '2019-07-06T13:47:17.356Z', 'lastTradeTimestamp': None, 'symbol': 'BNB/BTC', 'type': 'limit', 'side': 'sell', 'price': 0.0030952, 'amount': 1.14, 'cost': 0.0, 'average': None, 'filled': 0.0, 'remaining': 1.14, 'status': 'open', 'fee': None, 'trades': None} 136 | ] 137 | 138 | """ 139 | 140 | # 获取close_orders 141 | closed_orders = binance.fetch_closed_orders('BTC/USDT') 142 | print(closed_orders) 143 | 144 | 145 | # binance.post_order_id_cancel({ 146 | # }) 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /ccxt_study/ccxt_01.py: -------------------------------------------------------------------------------- 1 | import ccxt 2 | import time 3 | import pandas as pd 4 | print(ccxt.exchanges) 5 | 6 | huobipro = ccxt.huobipro({'urls': { 7 | 'logo': 'https://user-images.githubusercontent.com/1294454/27766569-15aa7b9a-5edd-11e7-9e7f-44791f4ee49c.jpg', 8 | 'api': { 9 | 'market': 'https://api.huobi.br.com', 10 | 'public': 'https://api.huobi.br.com', 11 | 'private': 'https://api.huobi.br.com', 12 | 'zendesk': 'https://huobiglobal.zendesk.com/hc/en-us/articles', 13 | }, 14 | 'www': 'https://www.huobi.pro', 15 | 'referral': 'https://www.huobi.br.com/en-us/topic/invited/?invite_code=rwrd3', 16 | 'doc': 'https://github.com/huobiapi/API_Docs/wiki/REST_api_reference', 17 | 'fees': 'https://www.huobi.pro/about/fee/', 18 | }}) 19 | 20 | 21 | ## 方法一: 设置apiKey和secret 22 | # binance = ccxt.binance({ 23 | # 'apiKey': 'XXXX', 24 | # 'secret': 'XXXXX' 25 | # }) 26 | 27 | ## 方法二:设置apiKey和secret 28 | # binance.secret = 'xxxx' 29 | # binance.apiKey = 'xxxxxx' 30 | 31 | 32 | 33 | 34 | # huobipro.loadMarkets() 35 | # huobipro.load_markets() 36 | # 37 | # print(huobipro.symbols) 38 | 39 | # binance.load_markets() # EOS/BTC 40 | # print(binance.symbols) 41 | 42 | # huobipro.fetchOHLCV() 43 | 44 | 45 | # ticker 46 | 47 | symbol = 'BTC/USDT' 48 | # huobi_btc_ticker = huobipro.fetch_ticker(symbol) 49 | # binance_btc_ticker = binance.fetch_ticker(symbol) 50 | # print(huobi_btc_ticker) 51 | # print(binance_btc_ticker) 52 | # 53 | 54 | 55 | # 获取开盘价、最高价、最低价、收盘价、成交量 OHLCV 56 | 57 | 58 | # ohlcv = binance.fetch_ohlcv(symbol, timeframe='15m') 59 | # # print(ohlcv) 60 | # df = pd.DataFrame(ohlcv) # open_time , open , high, low , close 61 | # print(df) 62 | # 63 | # balance = binance.fetch_balance() 64 | # print(balance) 65 | 66 | 67 | # exchange = ccxt.okex({'urls': { 68 | # 'logo': 'https://user-images.githubusercontent.com/1294454/32552768-0d6dd3c6-c4a6-11e7-90f8-c043b64756a7.jpg', 69 | # 'api': { 70 | # 'web': 'https://www.okex.me/v2', 71 | # 'public': 'https://www.okex.me/api', 72 | # 'private': 'https://www.okex.me/api', 73 | # }, 74 | # 'www': 'https://www.okex.com', 75 | # 'doc': [ 76 | # 'https://github.com/okcoin-okex/API-docs-OKEx.com', 77 | # 'https://www.okex.com/docs/en/', 78 | # ], 79 | # 'fees': 'https://www.okex.com/pages/products/fees.html', 80 | # 'referral': 'https://www.okex.com', 81 | # }}) 82 | # exchange.load_markets() 83 | # 84 | # 85 | # for symbol in exchange.markets: 86 | # market = exchange.markets[symbol] 87 | # if market['future']: 88 | # print('----------------------------------------------------') 89 | # print(symbol, exchange.fetch_ticker(symbol)) 90 | # time.sleep(exchange.rateLimit / 1000) -------------------------------------------------------------------------------- /ccxt_study/如何学习CCXT框架.md: -------------------------------------------------------------------------------- 1 | # 如何学习CCXT框架 2 | 3 | ## -------------------------------------------------------------------------------- /code_software.md: -------------------------------------------------------------------------------- 1 | # 课程相应的代码下载和软件下载链接 2 | 3 | 4 | ## 收费课程的代码下载链接: 5 | https://share.weiyun.com/88xtdom2 6 | 7 | ## youtube公开课的代码下载链接地址: 8 | https://github.com/51bitquant/51bitquant 9 | 10 | ## 手动交易下单软件下载链接: 11 | https://share.weiyun.com/F03qTiin 12 | 13 | ## howtrader 安装包下载链接: 14 | https://share.weiyun.com/LhKEc3cQ 15 | 16 | ## howtrader代码仓库 17 | https://github.com/51bitquant/howtrader 18 | 19 | ## vnpy课程的代码下载地址 20 | https://github.com/51bitqunat/course_codes 21 | 22 | 23 | ## 联系方式 24 | 如果遇到需要咨询的问题或者定制化开发,可以联系我微信: bitquant51 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /crawl_exchanges_datas/crawler.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | 1. 爬取交易所的数据, 并存入存入 CSV 里面. 4 | 2. 对交易所的数据进行清洗. 5 | 6 | 7 | 微信:bitquant51 8 | 9 | 火币交易所推荐码:asd43 10 | 币安推荐码: 22795115 11 | 币安推荐链接:https://www.binance.co/?ref=22795115 12 | Gateio交易所荐码:1100714 13 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 14 | 15 | 代码地址: https://github.com/ramoslin02/51bitqunt 16 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 17 | 18 | 1. bilibili.com 19 | 2. 优酷 youku.com 20 | 3. 百家号 baijiahao 21 | 4. 头条号 toutiao 22 | 5. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 23 | 24 | 25 | """ 26 | 27 | import pandas as pd 28 | import time 29 | import os 30 | import datetime 31 | import ccxt 32 | 33 | 34 | pd.set_option('expand_frame_repr', False) # 35 | 36 | TIMEOUT = 6 # 6 second 37 | BITFINEX_LIMIT = 5000 38 | BITMEX_LIMIT = 500 39 | BINANCE_LIMIT = 500 40 | 41 | 42 | def crawl_exchanges_datas(exchange_name, symbol, start_time, end_time): 43 | """ 44 | 爬取交易所数据的方法. 45 | :param exchange_name: 交易所名称. 46 | :param symbol: 请求的symbol: like BTC/USDT, ETH/USD等。 47 | :param start_time: like 2018-1-1 48 | :param end_time: like 2019-1-1 49 | :return: 50 | """ 51 | 52 | exchange_class = getattr(ccxt, exchange_name) # 获取交易所的名称 ccxt.binance 53 | exchange = exchange_class() # 交易所的类. 类似 ccxt.bitfinex() 54 | print(exchange) 55 | # exit() 56 | 57 | current_path = os.getcwd() 58 | file_dir = os.path.join(current_path, exchange_name, symbol.replace('/', '')) 59 | 60 | if not os.path.exists(file_dir): 61 | os.makedirs(file_dir) 62 | 63 | 64 | start_time = datetime.datetime.strptime(start_time, '%Y-%m-%d') 65 | end_time = datetime.datetime.strptime(end_time, '%Y-%m-%d') 66 | 67 | start_time_stamp = int(time.mktime(start_time.timetuple())) * 1000 68 | end_time_stamp = int(time.mktime(end_time.timetuple())) * 1000 69 | 70 | print(start_time_stamp) # 1529233920000 71 | print(end_time_stamp) 72 | 73 | limit_count = 500 74 | if exchange_name == 'bitfinex': 75 | limit_count = BITFINEX_LIMIT 76 | elif exchange_name == 'bitmex': 77 | limit_count = BITMEX_LIMIT 78 | elif exchange_name == 'binance': 79 | limit_count = BINANCE_LIMIT 80 | 81 | while True: 82 | try: 83 | 84 | print(start_time_stamp) 85 | data = exchange.fetch_ohlcv(symbol, timeframe='1m', since=start_time_stamp, limit=limit_count) 86 | df = pd.DataFrame(data) 87 | df.rename(columns={0: 'open_time', 1: 'open', 2: 'high', 3: 'low', 4: 'close', 5: 'volume'}, inplace=True) 88 | 89 | start_time_stamp = int(df.iloc[-1]['open_time']) # 获取下一个次请求的时间. 90 | 91 | filename = str(start_time_stamp) + '.csv' 92 | save_file_path = os.path.join(file_dir, filename) 93 | 94 | print("文件保存路径为:%s" % save_file_path) 95 | # exit() 96 | df.set_index('open_time', drop=True, inplace=True) 97 | df.to_csv(save_file_path) 98 | 99 | if start_time_stamp > end_time_stamp: 100 | print("完成数据的请求.") 101 | break 102 | 103 | time.sleep(3) 104 | 105 | except Exception as error: 106 | print(error) 107 | time.sleep(10) 108 | 109 | 110 | def sample_datas(exchange_name, symbol): 111 | """ 112 | 113 | :param exchange_name: 114 | :param symbol: 115 | :return: 116 | """ 117 | path = os.path.join(os.getcwd(), exchange_name, symbol.replace('/', '')) 118 | print(path) 119 | 120 | # exit() 121 | 122 | file_paths = [] 123 | for root, dirs, files in os.walk(path): 124 | if files: 125 | for file in files: 126 | if file.endswith('.csv'): 127 | file_paths.append(os.path.join(path, file)) 128 | 129 | file_paths = sorted(file_paths) 130 | all_df = pd.DataFrame() 131 | 132 | for file in file_paths: 133 | df = pd.read_csv(file) 134 | all_df = all_df.append(df, ignore_index=True) 135 | 136 | all_df = all_df.sort_values(by='open_time', ascending=True) 137 | 138 | print(all_df) 139 | 140 | return all_df 141 | 142 | # for index, item in all_df.iterrows(): 143 | # try: 144 | # dt = (pd.to_datetime(item['open_time'], unit='ms')) 145 | # print(dt) 146 | # dt = datetime.datetime.strptime(str(dt), '%Y-%m-%d %H:%M:%S') # 2018-01-01 17:36:00:42 147 | # print(dt) 148 | # except: 149 | # dt = (pd.to_datetime(item['open_time'], unit='ms')) 150 | # print(dt) 151 | 152 | def clear_datas(exchange_name, symbol): 153 | df = sample_datas(exchange_name, symbol) 154 | # print(df) 155 | # exit() 156 | # df['open_time'] = df['open_time'].apply(lambda x: time.mktime(x.timetuple())) 157 | # # 日期.timetuple() 这个用法 通过它将日期转换成时间元组 158 | # # print(df) 159 | # df['open_time'] = df['open_time'].apply(lambda x: (x // 60) * 60 * 1000) 160 | df['open_time'] = df['open_time'].apply(lambda x: (x//60)*60) 161 | print(df) 162 | df['Datetime'] = pd.to_datetime(df['open_time'], unit='ms') + pd.Timedelta(hours=8) 163 | df.drop_duplicates(subset=['open_time'], inplace=True) 164 | df.set_index('Datetime', inplace=True) 165 | print("*" * 20) 166 | print(df) 167 | symbol_path = symbol.replace('/', '') 168 | df.to_csv(f'{exchange_name}_{symbol_path}_1min_data.csv') 169 | 170 | 171 | if __name__ == '__main__': 172 | 173 | # crawl_exchanges_datas('binance', 'BTC/USDT', '2018-1-1', '2018-3-1') 174 | # crawl_exchanges_datas('bitmex', 'BTC/USD', '2018-1-1', '2018-3-1') 175 | # crawl_exchanges_datas('bitfinex', 'BTC/USDT', '2018-1-1', '2019-7-22') 176 | 177 | # sample_datas('bitfinex', 'BTC/USD') 178 | clear_datas('bitfinex', 'BTC/USD') 179 | 180 | pass 181 | -------------------------------------------------------------------------------- /huobi_api/huobi.py: -------------------------------------------------------------------------------- 1 | """ 2 | 微信:Griezmann_JR 3 | 火币交易所推荐码:asd43 4 | 币安推荐码: 22795115 5 | 币安推荐链接:https://www.binance.co/?ref=22795115 6 | Gateio交易所荐码:1100714 7 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 8 | 9 | 代码地址: https://github.com/ramoslin02/51bitqunt 10 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 11 | 12 | 1. bilibili.com 13 | 2. 优酷 youku.com 14 | 3. 百家号 baijiahao 15 | 4. 头条号 toutiao 16 | 5. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 17 | 18 | """ 19 | 20 | 21 | """ 22 | 什么是API: Application Programming Interface, 应用程序接口. 23 | 简单的说是通过 网络请求 给定的资源路径 可以获取到数据或者跟服务器进行 数据交换或者交互 24 | 25 | 火币文档介绍:https://huobiapi.github.io/docs/spot/v1/cn/#185368440e 26 | baseURL: https://api.huobi.pro # 科学上网 27 | https://api.huobi.br.com 28 | 29 | 限频规则 : 现货/杠杆(api.huobi.pro) 10秒100次 单个API Key 维度限制 30 | 31 | """ 32 | 33 | 34 | """ 35 | python3.7演示 获取火币的api行情数据 36 | """ 37 | 38 | # BASEURL = 'https://api.huobi.br.com' 39 | # currencys = '/v1/common/currencys' 40 | # 41 | # currencys_url = BASEURL + currencys 42 | # print(currencys_url) 43 | # import requests 44 | # 45 | # resp = requests.get(currencys_url) 46 | # print(resp) 47 | # print(resp.status_code) 48 | # print(resp.json()) 49 | # r_json = resp.json() 50 | # data = r_json['data'] 51 | # # print(data) 52 | # # print() 53 | # for d in data: 54 | # print(d) 55 | 56 | import requests 57 | import pandas as pd 58 | import time 59 | pd.set_option('expand_frame_repr', False) 60 | pd.set_option('display.max_rows', 1000) 61 | 62 | # 请求行数据, Kline data 63 | 64 | # url = 'https://api.huobi.br.com/market/history/kline?period=30min&size=1000&symbol=ethusdt' 65 | # resp = requests.get(url) 66 | # # print(resp) 67 | # # print(resp.json()) 68 | # resp_json = resp.json() 69 | # # print(resp_json['status']) 70 | # data_list = resp_json['data'] 71 | # # for data in data_list: 72 | # # print(data) 73 | # 74 | # df = pd.DataFrame(data_list) 75 | # print(df) 76 | 77 | # /Users/wanglin/anaconda3/lib/python3.7/site-packages/ccxt/base/exchange.py", 78 | 79 | # 获取ticker 80 | symbol = 'ethusdt' 81 | url = 'https://api.huobi.br.com' + '/market/detail/merged' + '?' + 'symbol=' + symbol 82 | print(url) 83 | resp = requests.get(url) 84 | # print(resp.json()) 85 | 86 | ticker = resp.json()['tick'] 87 | print(ticker) 88 | 89 | print(ticker['ask']) 90 | print(ticker['bid']) 91 | 92 | print("卖价:", ticker['ask'][0]) 93 | print("--"*10) 94 | print("买家:", ticker['bid'][0]) 95 | 96 | 97 | 98 | while True: 99 | # 获取ticker 100 | symbol = 'ethusdt' 101 | url = 'https://api.huobi.br.com' + '/market/detail/merged' + '?' + 'symbol=' + symbol 102 | print(url) 103 | resp = requests.get(url) 104 | # print(resp.json()) 105 | 106 | ticker = resp.json()['tick'] 107 | print(ticker) 108 | 109 | print(ticker['ask']) 110 | print(ticker['bid']) 111 | 112 | print("卖价:", ticker['ask'][0]) 113 | print("--" * 10) 114 | print("买家:", ticker['bid'][0]) 115 | time.sleep(5) 116 | 117 | 118 | # import requests 119 | # import pandas as pd 120 | # pd.set_option('expand_frame_repr', False) 121 | # pd.set_option('display.max_rows', 1000) 122 | # 123 | # 124 | # resp = requests.get("https://api.huobi.br.com/market/history/kline?period=1day&size=200&symbol=btcusdt") 125 | # print(resp.status_code) 126 | # resp_json = resp.json() 127 | # print(resp_json['status']) 128 | # 129 | # df = pd.DataFrame(resp_json['data']) 130 | # print(df) 131 | -------------------------------------------------------------------------------- /learn-decimal.py: -------------------------------------------------------------------------------- 1 | # 如何利用decimal库来处理小数点问题 2 | # 学习如何使用decimal库来处理小数点 3 | 4 | 5 | # 文档地址: https://docs.python.org/zh-cn/3/library/decimal.html 6 | 7 | value1 = 0.0000223233 8 | print(value1) 9 | value2 =str("0.0000223233") 10 | print(value2) 11 | 12 | ## 四则运算 13 | 14 | 15 | from decimal import Decimal, ROUND_UP, ROUND_DOWN 16 | 17 | a = Decimal(10) 18 | print(a, type(a)) 19 | 20 | b = Decimal(10.12) # 二进制方式存储的 21 | print(b) 22 | 23 | c = Decimal(str(10.12)) 24 | print(c) 25 | # 26 | # # 注意事项: Decimal对象不能跟其他进行数字类型进行运算,要把它们转成同类型的数据 27 | # 28 | # c1 = c + 11.2 29 | # print(c1) 30 | 31 | c1 = c + Decimal(str(11.2)) 32 | print(c1) 33 | 34 | 35 | ## 价格精度的问题 36 | 37 | # btc, 38450.1, 38450.1234, 2500.12 38 | 39 | 40 | price1 = Decimal(str(38450.15676)) 41 | 42 | d = price1.quantize(Decimal("0.1")) 43 | print(d) 44 | 45 | 46 | price2 = Decimal(str(2560.24567)) 47 | 48 | price2 = price2.quantize(Decimal("0.01")) 49 | print(price2) 50 | 51 | ## round_up, round_down 52 | 53 | price3 = Decimal(str(2560.24867)) 54 | 55 | price3 = price3.quantize(Decimal("0.01"), rounding=ROUND_DOWN) 56 | print(price3) 57 | 58 | 59 | price4 = Decimal(str(2560.241224)) 60 | 61 | price4 = price4.quantize(Decimal("0.01"), rounding=ROUND_UP) 62 | print(price4) 63 | 64 | -------------------------------------------------------------------------------- /pandas_basic/pandas_basic1.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | 微信:Griezmann_JR 4 | 火币交易所推荐码:asd43 5 | 币安推荐码: 22795115 6 | 币安推荐链接:https://www.binance.co/?ref=22795115 7 | Gateio交易所荐码:1100714 8 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 9 | 10 | github代码地址: https://github.com/ramoslin02/51bitqunt 11 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 12 | 13 | 0. Youtube: https://www.youtube.com/channel/UCjCMoRi4dZ6LRV2KL_RP8KQ/videos 14 | 1. bilibili.com 51bitquant 15 | 2. 爱奇艺:https://www.iqiyi.com/u/1752521752 16 | 3. 优酷 youku.com 17 | 4. 百家号 baijiahao 18 | 5. 头条号 toutiao 19 | 6. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 20 | 21 | ##################################################### 22 | 1. pandas基础讲解. 23 | 24 | 25 | ##################################################### 26 | """ 27 | 28 | import pandas as pd # 别名 29 | # print(pd.__version__) 30 | 31 | pd.set_option('expand_frame_repr', False) # 当列太多时不换行 32 | pd.set_option('display.max_rows', 1000) # 最多显示行数. 33 | # pd.set_option('precision', 6) # 浮点数的精度】 34 | pd.set_option('display.float_format', lambda x:'%.2f' % x) # 设置不用科学计数法,保留两位小数. 35 | 36 | #更多设置可以参考文档:http://pandas.pydata.org/pandas-docs/stable/user_guide/options.html 37 | 38 | # =====导入数据 39 | import os 40 | print(os.path.dirname(__file__)) 41 | print(os.path.dirname(os.path.dirname(__file__))) 42 | 43 | # comma separate value , 44 | 45 | df = pd.read_csv(filepath_or_buffer= '../binance_api/1559978820000.csv', # '/Users/wanglin/51bitquant/51bitqunt/binance_api/1559978820000.csv', 46 | skiprows=1, 47 | # usecols=['open_time', 'open', 'close', 'high', 'low', 'volume'], 48 | # nrows=10 49 | ) 50 | # pd.read_excel() 51 | # pd.read_hdf() 52 | 53 | print(df) 54 | 55 | # df = pd.read_csv( 56 | # 该参数为数据在电脑中的路径 57 | # filepath_or_buffer='/Users/wanglin/51bitquant/51bitqunt/binance_api/1559978820000.csv', # 绝对路径. 58 | # filepath_or_buffer='../binance_api/1559978820000.csv', # 相对路径 59 | 60 | # skiprows=1, 61 | # sep=sep, , ; 62 | # delimiter=None, 63 | # Column and Index Locations and Names 64 | # header='infer', 65 | # names=None, 66 | # index_col=None, 67 | # usecols=None, 68 | # squeeze=False, 69 | # prefix=None, 70 | # mangle_dupe_ 71 | # General Parsing Configuration 72 | # dtype=None, 73 | # engine=None, 74 | # converters=None, 75 | # true_values=None, 76 | # false_values=None, 77 | # skiprows=None, 78 | # skipfooter=0, 79 | # nrows=None, 80 | # # NA and Missing Data Handling 81 | # na_values=None, 82 | # keep_default_na=True, 83 | # na_filter=True, 84 | # verbose=False, 85 | # skip_blank_lines=True, 86 | # # Datetime Handling 87 | # parse_dates=False, 88 | # infer_datetime_format=False, 89 | # keep_date_col=False, 90 | # date_parser=None, 91 | # dayfirst=False, 92 | # Error Handling 93 | # error_bad_lines=True, 94 | # warn_bad_lines=True, 95 | # ) 96 | 97 | 98 | # 还可以导入 read_table、read_excel、read_json 99 | 100 | # print(df) 101 | # print(df.dtypes) 102 | 103 | 104 | # =====看数据 105 | # print(df.shape) # 输出dataframe有多少行、多少列。 106 | # print(df.shape[0]) 107 | 108 | # print(df.columns) # 顺序输出每一列的名字 109 | # for col in df.columns: 110 | # print(col) 111 | # print(df.index) # 顺序输出每一行的名字 112 | # for index in df.index: 113 | # print(index) 114 | # 115 | 116 | 117 | # print(df.dtypes) # 数据每一列的类型不一样,比如数字、字符串、日期等。该方法输出每一列变量类型 118 | # print(df.head()) # 默认是5。与自然语言很接近 119 | # print(df.head(3)) # 看前3行的数据 120 | # print(df.tail(3)) # 看最后3行的数据,默认是5。 121 | # print(df.sample(n=3)) # 随机抽取3行, 122 | # print(df.sample(frac=0.3)) # 想要去固定比例的话,可以用frac参数 123 | # print(df.describe()) # 非常方便的函数,对每一列数据有直观感受;只会对数字类型的列有效 124 | 125 | 126 | ################## Pandas对数据的访问和操作###################### 127 | # print(df) 128 | # =====如何选取指定的行、列 129 | # print(df['open']) # 根据列名称来选取,读取的数据是Series类型 130 | # print(df['open', 'open_time']) 131 | # print(df[['open_time', 'close']]) # 同时选取多列,需要两个括号,读取的数据是DataFrame类型 132 | 133 | 134 | # 增加列 135 | # df["mark"] = "北京时间" 136 | # df["exchange"] = "Binance" 137 | # nums = [i for i in range(0, 940, 1)] 138 | # df['number'] = nums 139 | # print(df) 140 | 141 | # 对列进行计算 142 | 143 | df['rmb_price'] = df['close'] *7 144 | 145 | # print(df['close'] * 7) # 数字列直接加上或者乘以数字,对整列进行操作。 146 | df['total_trade'] = (df['close'] * df['volume']) # 计算两类的乘积。 147 | 148 | df = df[['open_time', 'open', 'high', 'low', 'close', 'rmb_price', 'total_trade', 'volume']] # 对列的数据进行筛选和显示. 149 | # print(df) 150 | # print(df.dtypes) 151 | # 时间计算. 152 | 153 | df['open_time'] = pd.to_datetime(df['open_time'], unit='ms') # UTC 0时区的时间,格林威治的时间。 154 | # print(df) 155 | 156 | df['open_time'] = df['open_time'] + pd.Timedelta(hours=8) 157 | # df['open_time'] = pd.to_datetime(df['open_time'], unit='ms') # unit of the arg (D,s,ms,us,ns) 158 | 159 | # 增加一天,Timedelta用于表示时间差数据,[weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds] 160 | 161 | # print(df) 162 | # print(df.dtypes) 163 | 164 | print(df) 165 | # # iloc操作:通过position来读取数据 loc 166 | # print(df.iloc[0]) # 以index选取某一行,读取的数据是Series类型 167 | # print(df.iloc[0]['open']) # 获取某一行某一列的元素的值 168 | # print(df.iloc[1:3]) # 选取在此范围内的多行,读取的数据是DataFrame类型 169 | # print(df.iloc[:, 1:3]) # 选取在此范围内的多列,读取的数据是DataFrame类型 170 | # print(df.iloc[1:3, 1:3]) # 读取指定的多行、多列,读取的数据是DataFrame类型 171 | # print(df.iloc[:, :]) # 读取所有行、所有列,读取的数据是DataFrame类型 172 | # print(df.iloc[-1]) # 获取最后一行的数据 173 | # print(df.iat[1, 1]) # 使用iat读取指定的某个元素。使用iloc也行,但是iat更高效。 174 | # 175 | 176 | 177 | # =====统计函数 178 | print(df['close'].mean()) # 求一整列的均值,返回一个数。会自动排除空值。 179 | print(df[['close', 'volume']].mean()) # 求两列的均值,返回两个数 180 | # print(df[['close', 'volume']]) 181 | 182 | 183 | # print(df[['close', 'volume']].mean(axis=1)) # 求两列的均值, axis=0或者1要搞清楚。 184 | # df['close_V'] = df[['close', 'volume']].mean(axis=1) 185 | # print(df) 186 | # axis=1,代表对整几列进行操作。axis=0(默认)代表对几行进行操作。 187 | # 实际中弄混很正常,多去试下,打印出来观察下. 188 | 189 | print(df['high'].max()) # 最大值 190 | print(df['low'].min()) # 最小值 191 | print(df['close'].std()) # 标准差 192 | print(df['close'].count()) # 非空的数据的数量 193 | print(df['close'].median()) # 中位数 194 | print(df['close'].quantile(0.25)) # 25%分位数 195 | # 还有其他的函数计算其他的指标,在实际使用中遇到可以自己搜索 196 | 197 | -------------------------------------------------------------------------------- /pandas_basic/pandas_basic2.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | 微信:Griezmann_JR 4 | 火币交易所推荐码:asd43 5 | 币安推荐码: 22795115 6 | 币安推荐链接:https://www.binance.co/?ref=22795115 7 | Gateio交易所荐码:1100714 8 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 9 | 10 | github代码地址: https://github.com/ramoslin02/51bitqunt 11 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 12 | 13 | 0. Youtube: https://www.youtube.com/channel/UCjCMoRi4dZ6LRV2KL_RP8KQ/videos 14 | 1. bilibili.com 51bitquant 15 | 2. 爱奇艺:https://www.iqiyi.com/u/1752521752 16 | 3. 优酷 youku.com 17 | 4. 百家号 baijiahao 18 | 5. 头条号 toutiao 19 | 6. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 20 | 21 | ##################################################### 22 | Pandas 基础讲解2 23 | 24 | DataFrame shift、 diff、pct_change函数 25 | 如何删除列、 还有数据排序、合并DataFrame、删除重复数据、reset_index重置索引、set_index设置索引 26 | 27 | 官方文档: http://pandas.pydata.org/pandas-docs/stable/api.html 28 | 29 | ##################################################### 30 | """ 31 | import pandas as pd 32 | import os 33 | 34 | pd.set_option('expand_frame_repr', False) # 当列太多时不换行 35 | # pd.set_option('display.max_rows', 1000) # 最多显示行数. 36 | # pd.set_option('precision', 6) # 浮点数的精度】 37 | # pd.set_option('display.float_format', lambda x:'%.2f' % x) # 设置不用科学计数法,保留两位小数. 38 | 39 | # print(os.path.dirname(__file__)) 40 | 41 | current_dir = os.path.dirname(os.path.dirname(__file__)) 42 | print(current_dir) 43 | 44 | file_name = '1560038820000.csv' 45 | 46 | path = current_dir + '/binance_api/' + file_name 47 | # /Users/wanglin/51bitquant/51bitqunt/binance_api/1560038820000.csv 48 | # /Users/wanglin/51bitquant/51bitqunt/binance_api/1560038820000.csv 49 | 50 | df = pd.read_csv(filepath_or_buffer=path) 51 | 52 | df = df[['open_time', 'open', 'high', 'low', 'close', 'volume']] 53 | # print(df) 54 | # exit() 55 | 56 | 57 | # shift类函数 58 | df['下个close'] = df['close'].shift(-1) # shift 表示移动,负数表示向上移动,正数表示向下移动 59 | df['上个close'] = df['close'].shift(1) 60 | # print(df) 61 | # # 读取上一行的数据,若参数设定为3,就是读取上三行的数据;若参数设定为-1,就是读取下一行的数据 62 | # print(df) 63 | 64 | # exit() 65 | # 删除某一列 66 | # del df['下个close'] # 删除某一列的方法 del dict 67 | # df = df[['open_time', 'open', 'high', 'low', 'close', 'volume', '下个close']] 68 | # print(df) 69 | # df.drop(['上个close'], axis=1, inplace=True) # 删除某一列的另外一种方式,inplace参数指是否替代原来的df 70 | # print(df) 71 | 72 | 73 | # diff 计算价格涨跌 74 | # df['涨跌'] = df['close'].diff(0) # 跟自己比较 difference 75 | # print(df) 76 | 77 | # df['涨跌'] = df['close'].diff(-1) # 当前的close 减去shift(-1) 78 | # print(df) 79 | # df['shift-1'] = df['close'].shift(-1) 80 | # df['涨跌计算'] = df['close'] - df['shift-1'] 81 | # print(df) 82 | 83 | # 涨跌幅度 84 | # df['涨跌幅'] = df['close'].pct_change(1) # 类似于diff,但是求的是两个数直接的比例,相当于求涨跌幅 pct = percentage change 85 | # print(df) 86 | # 87 | # df['shift1'] = df['close'].shift(1) 88 | # df['涨跌幅计算'] = (df['close'] - df['shift1'])/df['close'] 89 | # print(df) 90 | 91 | 92 | # cum(cumulative)类函数 accumulative 93 | # df['volume_cum'] = df['volume'].cumsum() # 该列的累加值 94 | # print(df[['volume', 'volume_cum']]) 95 | # df['涨'] = (df['涨跌幅'] + 1.0).cumprod() # 累乘 product 乘积的意思 产品 96 | # print(df) 97 | 98 | 99 | # 排序函数 100 | # print(df.sort_values(by=['open_time'], ascending=1)) # by参数指定按照什么进行排序,acsending 上升的意思,参数指定是顺序还是逆序,1顺序,0逆序 101 | # print(df.sort_values(by=['volume', 'open_time'], ascending=[0, 0])) # 按照多列进行排序 102 | # print(df) 103 | 104 | 105 | # 多个DataFrame上下合并操作,append操作 106 | 107 | df1 = pd.read_csv(filepath_or_buffer=current_dir + '/binance_api/1560218820000.csv') 108 | df2 = pd.read_csv(filepath_or_buffer=current_dir + '/binance_api/1560278820000.csv') 109 | # print(df1) 110 | # print(df2) 111 | 112 | # df3 = df1.append(df2) # # append操作,将df1和df2上下拼接起来。注意观察拼接之后的index。index可以重复 113 | # print(df3) 114 | df3 = df1.append(df2, ignore_index=True) # ignore_index参数,用户重新确定index 115 | # print(df3) 116 | df4 = df3.append(df2, ignore_index=True) 117 | # print(df3) 118 | # print(df4) 119 | # =====对数据进行去重 120 | # df3中有重复的行数,我们如何将重复的行数去除 121 | # df4.drop_duplicates( # duplicates 122 | # subset=['open_time'], # subset参数用来指定根据哪类类数据来判断是否重复。若不指定,则用全部列的数据来判断是否重复 123 | # keep='first', # 在去除重复值的时候,我们是保留上面一行还是下面一行?first保留上面一行,last保留下面一行,False就是一行都不保留 124 | # inplace=True 125 | # ) 126 | # print(df4) 127 | 128 | 129 | # =====其他常用重要函数 130 | 131 | # df4.reset_index(inplace=True, drop=False) # 重置index, 是否保留之前的index 132 | # df4.reset_index(inplace=True, drop=True) # 重置index, 是否保留之前的index 133 | # print(df4) 134 | 135 | # df4.set_index('open_time', inplace=True) 136 | # print(df4) 137 | 138 | # print(df4rename.(columns={'close': '收盘价', 'open': '开盘价'})) # rename函数给变量修改名字。使用dict将要修改的名字传给columns参数 139 | # print(df.empty) # 判断一个df是不是为空,此处输出不为空 140 | # df0 = pd.DataFrame() 141 | # print(df0) 142 | # print(df0.empty) 143 | # print(pd.DataFrame().empty) # pd.DataFrame()创建一个空的DataFrame,此处输出为空 144 | # print(df.T) # 转置 将数据转置,行变成列 145 | -------------------------------------------------------------------------------- /pandas_basic/pandas_read_muti_csv3.py: -------------------------------------------------------------------------------- 1 | """ 2 | 微信:Griezmann_JR 3 | 火币交易所推荐码:asd43 4 | 币安推荐码: 22795115 5 | 币安推荐链接:https://www.binance.co/?ref=22795115 6 | Gateio交易所荐码:1100714 7 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 8 | 9 | github代码地址: https://github.com/ramoslin02/51bitqunt 10 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 11 | 12 | 0. Youtube: https://www.youtube.com/channel/UCjCMoRi4dZ6LRV2KL_RP8KQ/videos 13 | 1. bilibili.com 51bitquant 14 | 2. 爱奇艺:https://www.iqiyi.com/u/1752521752 15 | 3. 优酷 youku.com 16 | 4. 百家号 baijiahao 17 | 5. 头条号 toutiao 18 | 6. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 19 | 20 | ##################################################### 21 | Pandas 如何批量导入数据 22 | 23 | 官方文档: http://pandas.pydata.org/pandas-docs/stable/api.html 24 | 25 | ##################################################### 26 | """ 27 | 28 | import pandas as pd 29 | import os 30 | 31 | pd.set_option('expand_frame_repr', False) 32 | 33 | project_dir = os.path.dirname(os.path.dirname(__file__)) 34 | # print(project_dir) 35 | 36 | csv_dir = project_dir + '/binance_api' 37 | # print(csv_dir) 38 | 39 | # for root, dirs, files in os.walk(csv_dir): 40 | # print('root:', root) # 当前的目录 41 | # print('dirs:', dirs) # 文件件加目录 42 | # print('files:', files) # 文件 43 | # print("**"*20) 44 | # 45 | # print("****"*10) 46 | # 批量读取文件名称 47 | csv_file_paths = [] 48 | 49 | for root, dirs, files in os.walk(csv_dir): 50 | # 当files不为空的时候 51 | if files: 52 | for f in files: 53 | if f.endswith('.csv'): 54 | file_path = os.path.join(root, f) 55 | # print(file_path) 56 | csv_file_paths.append(file_path) 57 | 58 | 59 | # 遍历文件名,批量导入数据 60 | all_df = pd.DataFrame() 61 | 62 | print(csv_file_paths) 63 | 64 | for file in sorted(csv_file_paths): 65 | print(file) 66 | # 导入数据 67 | df = pd.read_csv(file) 68 | # 合并数据 69 | all_df = all_df.append(df, ignore_index=True) 70 | 71 | # print(all_df) 72 | 73 | 74 | # 删除重复的数据. 75 | all_df.drop_duplicates(subset=['open_time'], inplace=True, keep='first') 76 | # print(all_df) 77 | 78 | 79 | all_df.sort_values(by=['open_time'], ascending=1, inplace=True) 80 | 81 | all_df['open_time'] = pd.to_datetime(all_df['open_time'], unit='ms') 82 | all_df = all_df[['open_time', 'open', 'high', 'low', 'close', 'volume']] 83 | 84 | 85 | # df['open_time'] = pd.to_datetime(df['open_time'], unit='ms') 86 | all_df.set_index('open_time', inplace=True) 87 | 88 | all_df.to_csv('binance_btc_1min.csv') 89 | print(all_df) 90 | exit() -------------------------------------------------------------------------------- /pandas_basic/pandas_resample_data4.py: -------------------------------------------------------------------------------- 1 | """ 2 | 微信:Griezmann_JR 3 | 火币交易所推荐码:asd43 4 | 币安推荐码: 22795115 5 | 币安推荐链接:https://www.binance.co/?ref=22795115 6 | Gateio交易所荐码:1100714 7 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 8 | 9 | github代码地址: https://github.com/ramoslin02/51bitqunt 10 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 11 | 12 | 0. Youtube: https://www.youtube.com/channel/UCjCMoRi4dZ6LRV2KL_RP8KQ/videos 13 | 1. bilibili.com 51bitquant 14 | 2. 爱奇艺:https://www.iqiyi.com/u/1752521752 15 | 3. 优酷 youku.com 16 | 4. 百家号 baijiahao 17 | 5. 头条号 toutiao 18 | 6. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 19 | 20 | ##################################################### 21 | Pandas对行情数据周期的转换. 22 | 23 | 官方文档: http://pandas.pydata.org/pandas-docs/stable/api.html 24 | 25 | resample 文档:http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.resample.html?highlight=resample 26 | 27 | ##################################################### 28 | """ 29 | 30 | import pandas as pd 31 | 32 | pd.set_option('expand_frame_repr', False) 33 | 34 | df = pd.read_csv('binance_btc_1min.csv') 35 | # print(df) 36 | # print(df.dtypes) 37 | 38 | df['open_time'] = pd.to_datetime(df['open_time']) 39 | 40 | # print(df.dtypes) 41 | # print(df) 42 | # exit() 43 | 44 | # df['open_time'] >= pd.to_datetime('2019-06-07 15:00:00') 45 | df = df[df['open_time'] >= pd.to_datetime('2019-06-07 15:00:00')] # 筛选时间周期的 df['open_time'] >= pd.to_datetime('2019-06-07 15:00:00') 46 | # print(df) 47 | # 48 | # exit() 49 | 50 | # 第一种方法,通过Series进行转换. 51 | # 将时间周期相关的列设置为索引index 52 | df.set_index('open_time', inplace=True) 53 | # 周期转换方法:resample 54 | rule_cycle = '1D' # rule_cycle='5T':意思是5分钟,意味着转变为5分钟数据 # 15T 1H 1D 一天 55 | 56 | cycle_df = pd.DataFrame() 57 | cycle_df['close'] = df['close'].resample(rule=rule_cycle).last() # last:取这5分钟的最后一行数据 58 | # # 开、高、低的价格,成交量 59 | cycle_df['open'] = df['open'].resample(rule=rule_cycle).first() # 五分钟内的第一个值就是开盘价 60 | cycle_df['high'] = df['high'].resample(rule=rule_cycle).max() # 五分钟内的最高价就是High 61 | cycle_df['low'] = df['low'].resample(rule=rule_cycle).min() # 五分钟内的最低价就是low 62 | cycle_df['volume'] = df['volume'].resample(rule=rule_cycle).sum() # 五分钟内的成交量的综合就是成交量 63 | 64 | print(cycle_df) 65 | exit() 66 | 67 | 68 | # 通过DataFrame直接进行转换. 69 | 70 | rule_cycle = '5T' 71 | df.set_index('open_time', inplace=True) 72 | cycle_df1 = df.resample(rule=rule_cycle).agg( 73 | {'open': 'first', 74 | 'high': 'max', 75 | 'low': 'min', 76 | 'close': 'last', 77 | 'volume': 'sum', 78 | }) 79 | 80 | print(cycle_df1) 81 | # exit() 82 | 83 | # 通过DataFrame直接进行转换. 84 | rule_cycle = '5T' 85 | # df.reset_index(drop=False, inplace=True) # 86 | cycle_df1 = df.resample(rule=rule_cycle, on='open_time').agg( 87 | {'open': 'first', 88 | 'high': 'max', 89 | 'low': 'min', 90 | 'close': 'last', 91 | 'volume': 'sum', 92 | }) 93 | 94 | 95 | 96 | 97 | cycle_df1 = cycle_df1[['open', 'high', 'low', 'close', 'volume']] 98 | print(cycle_df1) 99 | 100 | 101 | # 去除不必要的数据 去除一天都没有交易的周 102 | cycle_df1.dropna(subset=['open'], inplace=True) 103 | # 去除成交量为0的交易周期 104 | 105 | cycle_df1 = cycle_df1[cycle_df1['volume'] > 0] # cycle_df1['volume'] > 0 106 | print(cycle_df1) # 107 | 108 | """ 109 | B business day frequency 110 | C custom business day frequency (experimental) 111 | D calendar day frequency 112 | W weekly frequency 113 | M month end frequency 114 | SM semi-month end frequency (15th and end of month) 115 | BM business month end frequency 116 | CBM custom business month end frequency 117 | MS month start frequency 118 | SMS semi-month start frequency (1st and 15th) 119 | BMS business month start frequency 120 | CBMS custom business month start frequency 121 | Q quarter end frequency 122 | BQ business quarter endfrequency 123 | QS quarter start frequency 124 | BQS business quarter start frequency 125 | A year end frequency 126 | BA business year end frequency 127 | AS year start frequency 128 | BAS business year start frequency 129 | BH business hour frequency 130 | H hourly frequency 131 | T minutely frequency 132 | S secondly frequency 133 | L milliseonds 134 | U microseconds 135 | N nanoseconds 136 | """ 137 | -------------------------------------------------------------------------------- /python_abc/func.py: -------------------------------------------------------------------------------- 1 | # 函数(方法) 定义 2 | 3 | 4 | """ 5 | def 函数名称(参数1, 参数2): 6 | 程序语句 7 | """ 8 | 9 | # def print_hello(): 10 | # print("hello world") 11 | # 12 | # 函数调用(通过函数名加括号调用) 13 | # print_hello() 14 | 15 | 16 | # 带有参数的函数 17 | # def print_hello1(name): 18 | # print("hello world:", name) 19 | # print_hello1("stephen") 20 | 21 | # def print_hello2(name, age, score): 22 | # print("hello world:", name, age, score) 23 | # 24 | # 25 | # print_hello2("stephen", 20, 80) 26 | # 带有返回值的函数 27 | 28 | # def child_or_adult(age): 29 | # if age > 18: 30 | # return "adult" 31 | # else: 32 | # return "child" 33 | # 34 | # per = child_or_adult(15) 35 | # print(per) 36 | 37 | 38 | # 局部变量和全局变量 39 | # num = 100 40 | # def func(): 41 | # num = 123 42 | # print(num) 43 | # 44 | # func() 45 | 46 | # num = 100 47 | # def func(): 48 | # num += 100 49 | # # num = num + 100 50 | # print(num) 51 | # 52 | # func() 53 | 54 | # 函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义一个局部变量。 55 | #函数内部的变量名如果第一次出现,且出现在=后面,且该变量在全局域中已定义,则 56 | # 这里将引用全局变量,如果该变量在全局域中没有定义,当然会出现“变量未定义”的错误。例如: 57 | # num = 100 58 | # def func(): 59 | # x = num + 100 60 | # print(x) 61 | # 62 | # func() 63 | # print(num) 64 | 65 | 66 | 67 | # 只要是*使用*变量,而该变量在全局域中有定义,而在局部没有定义,则会使用全局变量。 68 | 69 | # num = 100 # 全局变量 70 | # def func(): 71 | # num = 200 # 局部变量 72 | # x = num + 100 73 | # print(x) 74 | # func() 75 | # print(num) 76 | 77 | # 函数中使用某个变量时,该变量名既有全局变量也有同名的局部变量,则会使用局部变量 78 | 79 | # num = 100 # 全局变量 80 | # def func(): 81 | # global num 82 | # num = 200 83 | # num += 100 # num = num + 100 84 | # print(num) 85 | # func() 86 | # print(num) 87 | 88 | # 直接敲main 89 | # if __name__ == '__main__': 90 | # pass 91 | 92 | if __name__ == '__main__': 93 | pass 94 | # 面向对象编程 95 | # self 96 | # 网易云课堂 97 | # imooc 98 | # 极客网 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | # 函数(方法):作用主要是提高代码可读性、维护性、还有开发效率 -------------------------------------------------------------------------------- /python_abc/list_dict.py: -------------------------------------------------------------------------------- 1 | # list 是列表,跟数组相似,列表的数据可以相同,可以不相同 增删改查 2 | 3 | # a = [] 4 | # b = ['a', 'b', 'c', 'd'] 5 | # print(a) 6 | # print(b) 7 | # print(type(a)) 8 | # print(type(b)) 9 | 10 | # 遍历列表 11 | # for value in b: 12 | # print(value) 13 | # print(a) 14 | 15 | # for index, value in enumerate(b): 16 | # print(index, value) 17 | # print(value) 18 | 19 | # 列表长度 20 | # print(len(b)) 21 | 22 | 23 | # 列表通过下标访问元素 24 | # print(b[0]) 25 | # print(b[2]) 26 | 27 | # 列表切片操作 28 | # print(b[0:2]) 29 | # print(b[1:]) 30 | # print(b[1:3]) 31 | # 列表元素查找 32 | # print(b.index('a')) 33 | # print(b.index('b')) 34 | # print(b.index('f')) 35 | 36 | 37 | # 列表排序 38 | # list2 = [1, 9, 4, 5, 8] 39 | # print(list2) 40 | 41 | # print(sorted(list2)) 42 | # list2.sort() 43 | # print(list2) 44 | # print(list2) 45 | 46 | # list2.reverse() 47 | # print(list2) 48 | 49 | # dict 字典,一组键值对 javascript 对象 50 | dict_0 = {} 51 | 52 | dict_1 = {"BTC": "比特币", 53 | "ETH": "以太坊", 54 | "XRP": "瑞波币", 55 | "LTC": "莱特币" 56 | } 57 | # print(dict_1) 58 | 59 | # dict 获取值 60 | for key in dict_1: 61 | # print(key, dict_1[key]) 62 | # print() 63 | # pass 64 | print(dict_1.get(key)) 65 | 66 | 67 | 68 | # dict 获取健 69 | # keys = dict_1.keys() 70 | # print(keys, type(keys)) 71 | 72 | # values = dict_1.values() 73 | # print(values) 74 | 75 | 76 | # dict插入值 77 | dict_0['EOS'] = '柚子' 78 | dict_0['HT'] = "火腿" 79 | 80 | print(dict_0) 81 | 82 | # 删除 83 | dict_0.pop('EOS') 84 | print(dict_0) 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /python_abc/loop.py: -------------------------------------------------------------------------------- 1 | # 条件判断语句 2 | 3 | """ 4 | if 条件(真假): 5 | 语句 6 | elif 条件: 7 | 语句 8 | elif 条件: 9 | 10 | ... 11 | else: 12 | 语句 13 | pass 14 | 15 | """ 16 | 17 | # score = 95 18 | 19 | # if score < 60: 20 | # print("不及格") 21 | # elif 60 <=score < 80: # 60 <= score < 80 22 | # print("良好") 23 | # elif score < 90: 24 | # print("优秀") 25 | # else: 26 | # print("杰出") 27 | 28 | 29 | # if score > 90: 30 | # print("杰出") 31 | # elif score > 80: 32 | # print("优秀") 33 | # elif score > 60: 34 | # print("良好") 35 | # else: 36 | # print("不及格") 37 | 38 | 39 | 40 | # for 循环 41 | 42 | fruits = ['苹果', '香蕉', '樱桃', '荔枝', '芒果'] 43 | 44 | # for 值 in list: 45 | # for fruit in fruits: 46 | # print(fruit) 47 | 48 | # for index, fruit in enumerate(fruits): 49 | # print(index, fruit) 50 | 51 | # print(help(range)) 52 | 53 | # while 循环 54 | """ 55 | while 条件判断: 56 | 程序语句 57 | pass 58 | """ 59 | 60 | # a = 0 61 | # while a <= 100: 62 | # print(a) 63 | # a += 1 64 | 65 | # print(help(range)) 66 | # for i in range(1, 100, 3): 67 | # print(i) 68 | 69 | # import time 70 | # # 无限循环 71 | # while True: 72 | # print("CTA策略运行") 73 | # time.sleep(5) 74 | 75 | 76 | # break 和 continue: 77 | ## - continue语句被用来告诉Python跳过当前循环块中的剩余语句,然后继续进行下一轮循环。 78 | ## - break 语句可以跳出 for 和 while 的循环体,结束当前的循环. 79 | 80 | # for letter in 'BTC/USDT': # 第一个实例 可迭代的对象 81 | # # print(letter) 82 | # if letter == 'U': 83 | # break 84 | # # continue 85 | # print('当前字母为 :', letter) 86 | # 87 | # print("*"*20) 88 | # for letter in 'BTC/USDT': # 第一个实例 可迭代的对象 89 | # # print(letter) 90 | # if letter == 'U': 91 | # # break 92 | # continue 93 | # print('当前字母为 :', letter) 94 | 95 | # 96 | 97 | 98 | var = 10 # 第二个实例 99 | while var > 0: 100 | print('当期变量值为 :', var) 101 | var = var - 1 102 | if var == 5: 103 | break 104 | 105 | print("*" * 20) 106 | var = 10 # 第二个实例 107 | while var > 0: 108 | var = var - 1 109 | if var == 5: # 变量为 5 时跳过输出 110 | continue 111 | print('当前变量值 :', var) 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /python_abc/str_and_num.py: -------------------------------------------------------------------------------- 1 | # python 定义变量 只能以字母和下划线开头, 书写全部以英文半角输入法. 2 | 3 | """ 4 | a = "hello world" 5 | a23 = "hello world" 6 | print(a23) 7 | 8 | """ 9 | 10 | 11 | 12 | # 整数和浮点数 +、- * / %(求余数) **, 保留小数点 13 | 14 | # a1 = 12 15 | # a2 = 12.5 16 | # 17 | # c = a1 + a2 18 | # print(c) 19 | # 20 | # d = a1 - a2 21 | # print(d) 22 | 23 | # e = a1 * a2 24 | # print(e) 25 | # 26 | # e = a1 / a2 27 | # print(e) 28 | 29 | # 30 | # a1 = 5 31 | # a2 = 3 32 | # e = a1 % a2 33 | # print(e) 34 | 35 | # a1 = 2 36 | # a2 = 2 37 | # e = a1 ** a2 38 | # print(e) 39 | 40 | # a1 = 12.9566 41 | # c = round(a1, 2) 42 | # print(c) 43 | 44 | 45 | # a = True 46 | # b = False 47 | # 48 | # print(a) 49 | # print(b) 50 | 51 | # 比较运算 > < >= <= == != 52 | 53 | # print(3 > 2) # True 54 | # print(3 < 2) # False 55 | # print(3>=2) # True 56 | # print(3<=3) # True 57 | # print(3==2) # False 58 | # print(3!=2) # True 59 | 60 | 61 | # 布尔值 布尔运算and or & | 62 | 63 | # a = (3>2) and (1<2) # True 64 | # # print(a) 65 | 66 | # a = (3>2) & (1<2) # True 67 | # print(a) 68 | 69 | # b = (3>2) | (1>2) # True 70 | # print(b) 71 | 72 | # b = (3 > 2) or (1>2) # True 73 | # print(b) 74 | 75 | 76 | # 代码注释 ,单行注释和多行注释 77 | 78 | 79 | # 操作符 type, help函数, 查看帮助文档, 按住command 点击查看. 80 | # print(help(round)) 81 | 82 | 83 | # 字符串定义 String 以单引号',双引号'',三引号''' 开始,同样符号结束 84 | 85 | hello = "hello world" 86 | hello1 = 'hello world' 87 | hello2 = '''Hello world''' 88 | # print(hello) 89 | # print(hello1) 90 | # print(hello2) 91 | 92 | # 字符串截取和运算 * + 通过下标来运算, 分割, 替换, 大写小写转变 93 | 94 | # print(hello[1]) 95 | 96 | # a = hello + "我" 97 | # print(a) 98 | # 99 | # print(hello * 3) # "hello world" + "hello world" + "hello world" 100 | 101 | 102 | # a = hello.split(' ') 103 | # # print(a) 104 | # 105 | # for value in a: 106 | # print(value) 107 | 108 | # a = hello.upper() # 转成大写 109 | # print(a) 110 | # 111 | # b = a.lower() # 转成小写 112 | # print(b) 113 | 114 | 115 | # 替换 116 | 117 | symbol = "BTC/USDT" 118 | # print(symbol.split('/')) 119 | symbol1 = 'btc_usdt' 120 | symbol2 = symbol1.upper() 121 | print(symbol2) 122 | 123 | symbol3 = symbol2.replace('_', '/') 124 | print(symbol3) 125 | 126 | print(symbol == symbol3) 127 | 128 | -------------------------------------------------------------------------------- /technical_indicators/technical_indicators.md: -------------------------------------------------------------------------------- 1 | # technical indicator 技术分析指标 2 | 3 | 1. 什么是技术指标. 4 | 5 | 6 | 7 | ## 学习资料 8 | 9 | 1. 各种指标的计算公式以及统计的含义. 10 | 1.1 https://school.stockcharts.com/doku.php?id=technical_indicators 11 | 12 | 1.2 https://www.barchart.com/education/technical-indicators 13 | 14 | 比如MA指标,Moving Average 15 | https://school.stockcharts.com/doku.php?id=technical_indicators:moving_averages 16 | 17 | 如BBands 18 | https://www.barchart.com/education/technical-indicators/bollinger_bands 19 | 20 | 21 | ## 如何计算技术指标 22 | 23 | ### 使用Ta-Lib 24 | 25 | github地址:官方文档 https://github.com/mrjbq7/ta-lib 26 | 使用具体使用 27 | 28 | ### 结合pandas 计算 29 | 30 | ### Ta-Lib计算结果和交易所的数据结果不同原因 31 | 1. 数据可能有问题 # ema 32 | 2. 时间不一致 33 | 3. 计算指标的参数不一致 34 | 4. Ta-Lib的算法和交易所的算法不一样 35 | 36 | 37 | ## tradingView 简单介绍 38 | 如何写技术指标,研究行情. 39 | 40 | 41 | -------------------------------------------------------------------------------- /technical_indicators/technical_indicators.py: -------------------------------------------------------------------------------- 1 | """ 2 | 1. 技术指标讲解. 3 | 4 | 微信:bitquant51 5 | 火币交易所推荐码:asd43 6 | 币安推荐码: 22795115 7 | 币安推荐链接:https://www.binance.co/?ref=22795115 8 | Gateio交易所荐码:1100714 9 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 10 | 代码地址: https://github.com/ramoslin02/51bitqunt 11 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 12 | 13 | """ 14 | 15 | import ccxt 16 | import numpy as np 17 | import pandas as pd 18 | import talib as ta 19 | import time 20 | 21 | pd.set_option('expand_frame_repr', False) 22 | pd.set_option('display.max_rows', 1000) 23 | 24 | binance = ccxt.binance() 25 | bitmex = ccxt.bitmex() 26 | 27 | 28 | # limit = 500 29 | # since = time.time() * 1000 - limit * 60 * 5 * 1000 30 | # data = bitmex.fetch_ohlcv('BTC/USD', timeframe='5m', since=since, limit=limit) 31 | # df = pd.DataFrame(data, columns={'close_time': 0, 'open': 1, 'high': 2, 'low':3 , 'close':4, 'volume': 5}) 32 | # df['close_time'] = pd.to_datetime(df['close_time'], unit='ms') + pd.Timedelta(hours=8) 33 | # print(df) 34 | 35 | data = binance.fetch_ohlcv('BTC/USDT', timeframe='15m') 36 | df = pd.DataFrame(data, columns={'open_time': 0, 'open': 1, 'high': 2, 'low':3 , 'close':4, 'volume': 5}) 37 | df['open_time'] = pd.to_datetime(df['open_time'], unit='ms') + pd.Timedelta(hours=8) 38 | 39 | # df['sma'] = ta.SMA(df['close'], timeperiod=20) 40 | # df['ma'] = ta.MA(df['clsoe'], timeperiod=20, matype=1) 41 | # df['ema'] = ta.EMA(df['clsoe'], timeperiod=20) 42 | # 43 | # # 如何学习Ta-Lib 文档:http://mrjbq7.github.io/ta-lib/ 44 | # print(help(ta.SMA)) 45 | # print(help(ta.MA)) 46 | # print(help(ta.MA_Type)) 47 | # ndarray, numpy array, pd.Series 48 | # print(help(ta.BBANDS)) 49 | # 50 | # df['upperband'],df['middleband'], df['lowerband'] = ta.BBANDS(df['close'], timeperiod=20, nbdevup=3.0, nbdevdn=3.0, matype=0) 51 | # print(df) 52 | # exit() 53 | 54 | # df['sma'] = talib.SMA(df['close'], timeperiod=20) 55 | # df['ma'] = talib.MA(df['close'], timeperiod=20, matype=1) 56 | # df['NATR'] = talib.NATR(df['high'], df['low'],df['clsoe'],timeperiod=14) 57 | # talib.BBANDS() 58 | 59 | 60 | 61 | # 自己计算技术指标 62 | """ 63 | 1. 30期CMI = 100*absvalue(close - 30期前close)/(30期最高价-30期最低价) 64 | AvgCMI = CMI的30期移动平均值 65 | AVGCMI如果小于20, 我们认为市场处于盘整状态。 66 | 如果大于等于20,我们认为市场处于趋势状态。 67 | 68 | """ 69 | 70 | 71 | print(help(ta.STOCH)) # 72 | 73 | 74 | def calculate_cmi_indicator(df): # RSI 75 | 76 | cmi_period = 30 77 | cmi_ma_period = 10 78 | roc = df['close'].diff(cmi_period) 79 | h1 = ta.MAX(df['high'], cmi_period) - ta.MIN(df['low'], cmi_period) 80 | cmi = abs(roc / h1) * 100 81 | cmi_ma = ta.MA(cmi, cmi_ma_period) # rolling. 82 | return cmi_ma 83 | 84 | 85 | def rsi(close_prices, length): 86 | """ 87 | :param df: 计算rsi相对强弱指标. 88 | :param rsi_length: rsi的长度. 89 | :return: 90 | """ 91 | deltas = np.diff(close_prices) 92 | seed = deltas[:length + 1] 93 | up = seed[seed >= 0].sum() / length 94 | down = -seed[seed < 0].sum() / length 95 | rs = up / down 96 | rsi = np.zeros_like(close_prices) 97 | rsi[:length] = 100. - 100. / (1. + rs) 98 | 99 | for i in range(length, len(close_prices)): 100 | delta = deltas[i - 1] # cause the diff is 1 shorter 101 | if delta > 0: 102 | upval = delta 103 | downval = 0. 104 | else: 105 | upval = 0. 106 | downval = -delta 107 | 108 | up = (up * (length - 1) + upval) / length 109 | down = (down * (length - 1) + downval) / length 110 | 111 | rs = up / down 112 | rsi[i] = 100. - 100. / (1. + rs) 113 | 114 | return rsi 115 | 116 | 117 | 118 | 119 | def stoch_rsi(df, length, k_smooth, d_smooth): 120 | 121 | """ 122 | 123 | STOCHRSI(...) 124 | STOCHRSI(real[, timeperiod=?, fastk_period=?, fastd_period=?, fastd_matype=?]) 125 | 126 | Stochastic Relative Strength Index (Momentum Indicators) 127 | 128 | Inputs: 129 | real: (any ndarray) 130 | Parameters: 131 | timeperiod: 14 132 | fastk_period: 5 133 | fastd_period: 3 134 | fastd_matype: 0 135 | Outputs: 136 | fastk 137 | fastd 138 | 139 | None 140 | 141 | :param df: 142 | :param length: 143 | :param k_smooth: 144 | :param d_smooth: 145 | :return: 146 | """ 147 | 148 | """ 149 | 150 | study(title="StochRSI", shorttitle="StochRSI") 151 | source = close 152 | lengthRSI = input(14, minval=8), 153 | lengthStoch = input(14, minval=5) 154 | smoothK = input(3,minval=3), 155 | smoothD = input(3,minval=3) 156 | OverSold = input(25), OverBought = input(75) 157 | rsi1 = rsi(source, lengthRSI) 158 | k = sma(stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK) 159 | d = sma(k, smoothD) 160 | hline(OverSold,color=blue) 161 | hline(OverBought,color=blue) 162 | plot(k, color=black,title="k-line") 163 | plot(d, color=fuchsia,title="d-line",linewidth=1) 164 | 165 | stoch 计算公式. 100 * (close - lowest(low, length)) / (highest(high, length) - lowest(low, length)) 166 | 167 | :param df: dataFrame 168 | :param rsi_length: 计算相对相若指标 169 | :param stoch_length: 计算stoch长度 170 | :param k_smooth: 计算k的平滑值 171 | :param d_smooth: 计算d的平滑值. 172 | :return: 173 | 174 | """ 175 | df['rsi'] = ta.RSI(df['close'], timeperiod=length) 176 | df['rsi_H'] = df['rsi_'].rolling(window=length).max() 177 | df['rsi_L'] = df['rsi_'].rolling(window=length).min() 178 | # df.apply(lambda x: print(x), axis=1) 179 | df['k_series'] = df.apply(lambda x: 100 * (x['rsi'] - x['rsi_L']) / (x['rsi_H'] - x['rsi_L']), 180 | axis=1) 181 | # 100 * (df['close'] - df['rsi_L'])/(df['rsi_H'] - df['rsi_L']) 182 | 183 | fastK = ta.SMA(df['k_series'], timeperiod=k_smooth) 184 | faskd = ta.SMA(fastK, timeperiod=d_smooth) 185 | 186 | del df['k_series'] 187 | del df['rsi_H'] 188 | del df['rsi_L'] 189 | del df['rsi_'] 190 | 191 | return (fastK, faskd) 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /wallet/钱包.md: -------------------------------------------------------------------------------- 1 | 2 | # 微信:bitquant51 3 | 4 | # 视频YouTube,B站上可以找到, 搜索51bitquant 5 | 6 | # 数字货币钱包 7 | 首先钱包并不能存储你的数字货币的资产,只是具有查询等功能,钱包里面的钱 8 | 是存储在去中心化的区块链上。所以说谁拥有了数字货币的钱包的私钥,谁就是这个 9 | 资产的主人。 10 | 11 | 12 | 1. 可以注册钱包地址,管理钱包的信息 13 | 2. 一般是轻钱包,可以查询自己账号的一些交易信息 14 | 3. 可以发起转账 15 | 4. 集成多个主流数字货币 16 | 17 | # 如何注册钱包 18 | 1. 通过keystore方式 19 | 2. 通过助词 20 | 21 | # 如何查看链上交易: 22 | 1. BTC的区块浏览器:https://btc.com/ 通过区块浏览器上可以查询到 23 | 2. ETH区块浏览器: https://etherscan.io/ 24 | 3. 其他的通过其相应的区块浏览器上查询 25 | 26 | 27 | # Plustoken钱包的地址: 14BWH6GmVoL5nTwbVxQJKJDtzv4y5EbTVm -------------------------------------------------------------------------------- /weixinbot/AI公司代码.pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/51bitquant/bitquant/a19e703238a7d4c06240a0aa3d31699ad8a7e68f/weixinbot/AI公司代码.pic.jpg -------------------------------------------------------------------------------- /weixinbot/wechat_orderbot.py: -------------------------------------------------------------------------------- 1 | """ 2 | 微信:bitquant51 3 | 火币交易所推荐码:asd43 4 | 币安推荐码: 22795115 5 | 币安推荐链接:https://www.binance.co/?ref=22795115 6 | Gateio交易所荐码:1100714 7 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 8 | 9 | 代码地址: https://github.com/ramoslin02/51bitqunt 10 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 11 | 12 | 1. B站 51bitquant 13 | 2. 优酷: 51bitquant 14 | 3. 百家号: 51bitquant 15 | 16 | """ 17 | 18 | __author__ = '51bitquant' 19 | 20 | # 微信交易所机器人, 实现下单, 插叙账户功能. 21 | from wxpy import * 22 | import ccxt 23 | 24 | binance = ccxt.binance({'apiKey':'jXD7h5RoGa7VjZP5mWhsNAO4Fg7J6mkveG4a8MP8QsuzMg8JqIwksB6066RJcRYm', 25 | 'secret': 'kwg6EjlbtBzlKdZ97byEA4sc8EMsssxtLD7luibl5BbEZtfSXR2YNbCG7Pxd0v4G' 26 | }) 27 | 28 | bot = Bot(cache_path=True, console_qr=-2) # Bot() # 29 | 30 | # # 查找好友. 31 | bitquant = bot.friends().search('51bitquant')[0] # 搜索昵称为bitquant51的朋友, 微信为:bitquant51 32 | print(bitquant) 33 | 34 | 35 | @bot.register([bitquant], msg_types=TEXT) 36 | def receive_message(msg: Message): 37 | txt = msg.text 38 | # txt的格式 #ex=binance, price=300.8, 'amount'=1, symbol=BTC/USDT, type=limit# 39 | # #symbol, price, amount, type, side# 看你对对订单的数据定义. 40 | print(txt) 41 | 42 | try: 43 | txt = txt.strip(' ') 44 | 45 | if txt.find("下单") >= 0: 46 | bitquant.send("#交易所名称如binance/huobipro/okex等,交易对如BTC/USDT,下单价格,下单数量,订单类型如limit/market,买或卖如buy/sell#" 47 | ) 48 | 49 | if txt.startswith('#') and txt.endswith("#"): 50 | txt = txt.strip('#') # 去掉头尾的两个#字符. 51 | order_fields = txt.split(',') # 分割键值对. #binance, BTC/USDT, 10000, 0.01, limit, buy# 52 | order_datas = [] 53 | 54 | for item in order_fields: 55 | order_datas.append(item.strip(" ")) 56 | # 把空白字符给处理掉, 如下面的输入. 57 | #binance, BTC/USDT, 9000, 0.01, limit, buy# 58 | 59 | print(order_datas) 60 | if len(order_datas) >= 6: 61 | create_order(order_datas[0], order_datas[1], order_datas[2], order_datas[3], order_datas[4], order_datas[5]) 62 | except Exception as error: 63 | bitquant.send(error) 64 | 65 | 66 | # 还可处理撤单、以及各种逻辑. 67 | #binance, cancel_id# #binance,xxxxxxx# 68 | 69 | #binance, 查询账户# 70 | 71 | def create_order(exchange, symbol, price, amount, order_type, side): 72 | 73 | try: 74 | if exchange == 'binance': # 币安的 75 | 76 | price = float(price) 77 | amount = float(amount) 78 | print(f"symbol={symbol}, type={order_type}, price={price} amount={amount}, side={side}") 79 | 80 | order = binance.create_order(symbol=symbol, type=order_type, price=price, amount=amount, side=side) 81 | # ccxt.huobipro().create_order() 82 | print(order) 83 | bitquant.send(order) 84 | 85 | elif exchange == 'huobi': # 火币的. 86 | pass # 自己去实现下. 87 | 88 | else: 89 | pass 90 | 91 | except Exception as error: 92 | print(error) 93 | bitquant.send(error) 94 | 95 | embed() # 进入 Python 命令行、让程序保持运行 96 | 97 | # 解答一些问题 98 | 99 | # 交易所订单的问题 type, 100 | # 解答一些疑问, 微信登录问题 101 | # 火币的接口 102 | -------------------------------------------------------------------------------- /weixinbot/weixinbot.py: -------------------------------------------------------------------------------- 1 | """ 2 | 微信:Griezmann_JR 3 | 火币交易所推荐码:asd43 4 | 币安推荐码: 22795115 5 | 币安推荐链接:https://www.binance.co/?ref=22795115 6 | Gateio交易所荐码:1100714 7 | Bitmex交易所推荐码:SzZBil 或者 https://www.bitmex.com/register/SzZBil 8 | 9 | 代码地址: https://github.com/ramoslin02/51bitqunt 10 | 视频更新:首先在Youtube上更新,搜索51bitquant 关注我 11 | 12 | 1. B站 51bitquant 13 | 2. 优酷: 51bitquant 14 | 3. 百家号: 51bitquant 15 | 4. 头条号: 51bitquant 16 | 5. 爱奇艺: 量化交易51bitquant 17 | 6. 简书博客:https://www.jianshu.com/u/9afa76d7d7f0 18 | 19 | """ 20 | 21 | import wxpy # pip install -U wxpy 或者 pip install -U wxpy -i "https://pypi.doubanio.com/simple/" 22 | 23 | """ 24 | 1. wxpy github地址: https://github.com/youfou/wxpy 25 | 2. wxpy文档地址: https://wxpy.readthedocs.io/zh/latest/ 26 | 2. 要有两个微信才能测试, 其中一个微信必须是老号,且要经过实名认证, 身份证和银行卡, 另一个作为测试使用 27 | 新号老号都可以. 28 | 29 | """ 30 | 31 | from wxpy import * 32 | import requests 33 | 34 | bot = Bot(cache_path=True, console_qr=-2) # Bot() # 35 | 36 | 37 | # # 查找好友. 38 | bitquant = bot.friends().search('51bitquant')[0] # 搜索昵称为51bitquant的朋友 39 | bitquant_signal_group = bot.groups().search('51bitquant信号群')[0] # 搜索群名字为51bitquant信号群的群,该群要求添加到通讯录才可以找到。 40 | 41 | print(bitquant) 42 | # print(bitquant_signal_group) 43 | # 44 | # # 发送信息, 通过send的方法 45 | bitquant.send("Hello world") # 当前登录的这个微信账号,给他发送信息. 给bitquant发送信息 46 | # 47 | # # 注册相应的信息 48 | # 49 | # @bot.register() # 装饰器. 50 | # def print_others(msg): 51 | # print('收到的其他信息:-->', msg) 52 | 53 | # 54 | # # 回复 my_friend 的消息 (优先匹配后注册的函数!) 55 | # @bot.register([bitquant]) 56 | # def reply_my_friend(msg): 57 | # if msg.type == 'Text': 58 | # print("收到的信息:", msg.text) 59 | # content = msg.text.replace('吗', '') 60 | # content = content.replace('?', '!') # 英文的问号? 61 | # content = content.replace('?', '!') # 中文的问号? 62 | # print("回复的信息:", content) 63 | # 64 | # return content 65 | # 66 | # 自动接受新的好友请求 67 | # @bot.register(msg_types=FRIENDS) 68 | # def auto_accept_friends(msg): 69 | # # 接受好友请求 70 | # new_friend = msg.card.accept() 71 | # # 向新的好友发送消息 72 | # new_friend.send('哈哈,我自动接受了你的好友请求') 73 | 74 | # @bot.register([bitquant, bitquant_1], msg_types=TEXT), 注册多个人的信息, 且只处理TEXT文字类型. 75 | 76 | 77 | BASE_URL = 'https://api.huobi.br.com' 78 | currencys_url = BASE_URL + '/v1/common/currencys' 79 | resp = requests.get(currencys_url) 80 | currencys = [] 81 | if resp.status_code == 200: 82 | currencys = resp.json()['data'] 83 | 84 | print(currencys) 85 | 86 | # btcusdt 87 | 88 | # bchusdt --> bchbtc --> bcheth 89 | def request_symbol_price(symbol, sender): 90 | 91 | try: 92 | resp = requests.get(BASE_URL+'/market/detail/merged'+'?symbol='+symbol+'usdt') 93 | if resp.status_code == 200: 94 | tick = resp.json()['tick'] 95 | price_str = "火币"+ symbol+'/usdt'+'价格为: ', tick['bid'][0] 96 | print(price_str) 97 | sender.send(price_str) 98 | except Exception as error: 99 | try: 100 | resp = requests.get(BASE_URL + '/market/detail/merged' + '?symbol=' + symbol + 'btc') 101 | if resp.status_code == 200: 102 | tick = resp.json()['tick'] 103 | price_str = "火币" + symbol + '/btc' + '价格为: ', tick['bid'][0] 104 | print(price_str) 105 | sender.send(price_str) 106 | except Exception as error: 107 | try: 108 | resp = requests.get(BASE_URL + '/market/detail/merged' + '?symbol=' + symbol + 'eth') 109 | 110 | if resp.status_code == 200: 111 | tick = resp.json()['tick'] 112 | price_str = "火币" + symbol + '/eth' + '价格为: ', tick['bid'][0] 113 | print(price_str) 114 | sender.send(price_str) 115 | except Exception as error: 116 | pass 117 | 118 | 119 | @bot.register([bitquant, bitquant_signal_group], msg_types=TEXT) 120 | def receive_message(msg: Message): 121 | txt = msg.text 122 | sender = msg.sender 123 | print(msg.sender) 124 | print(msg.text) 125 | if txt in currencys: 126 | request_symbol_price(txt, sender) 127 | 128 | 129 | embed() # 进入 Python 命令行、让程序保持运行 -------------------------------------------------------------------------------- /安装包说明.txt: -------------------------------------------------------------------------------- 1 | # Binance 合约交易软件 2 | 3 | 合约快速下单交易软件 4 | 5 | ## 项目中有两个安装包 6 | .exe文件是window安装包 7 | .dmg文件是mac安装包 8 | 9 | ## 使用主要事项 10 | 1. 使用前,要连接交易所, 设置你的apikey 和secret, 11 | 生成apikey的时候,记得编辑你的api权限,设置它能够交易合约。 12 | 13 | 2. 关于代理主机和端口,如果本地使用,如果能够直接访问币安交易所,那么主机设置为空(不要填写任何东西),端口写0就可以。 14 | 如果你的电脑不能直接访问币安交易所,可以设置你的代理主机和端口号。 15 | 16 | 3. 软件只支持单向持仓, 在币安app,合约那里,点击偏好设置,设置持仓方向为单项持仓 17 | 18 | 4. 要交易的时候,要订阅交易对的行情,点击输入框那里,输入交易对,如BTCUSDT, 19 | ETHUSDT等 20 | 21 | 22 | ## 使用说明 23 | 24 | 1. 按下快捷键Z: 撤销所有订单 25 | 2. 按下快捷键X: 撤销最近一个订单 26 | 3. 其他功能的话需要自己配置. 27 | 28 | ## 软件风险 29 | 1. 本软件只是快速下单的工具,不能保证盈利,风险与本开发人员无关。 30 | 2. 请在使用前测试相应软件的功能是否正常 31 | 3. 本软件开发人员不承担任何风险,请在使用软件前了解相应的风险 32 | 4. 需要定制相应的功能请联系微信:bitquant51 33 | 34 | ## 软件下载链接: 35 | https://share.weiyun.com/F03qTiin -------------------------------------------------------------------------------- /币安智能链BSC之汉堡挖矿入门到精通.md: -------------------------------------------------------------------------------- 1 | # 币安智能链BSC之汉堡挖矿入门到精通 2 | 最近去中心化金融挖矿非常的火爆,从uniswap、sushi、红薯等等各种美食,币圈真是各个都是烹饪高手,在线十分的佩服。 3 | 4 | 那么今天给大家介绍一款大家常见的美食的做法-烤汉堡(Bake Hamburger),一款基于币安智能链的去中心挖矿, 通过提供流动性进行挖矿(AMM ,Auto Market Maker)。 5 | 6 | 7 | ## 流程如下: 8 | 1. 首先大家得去币安交易所买bnb, 注册链接地址: 9 | > https://www.binancezh.com/cn/futures/ref/51bitquant 10 | 11 | 2. 下载谷歌浏览器: chrome 12 | 13 | 3. 安装meta mask签名插件, 安装链接 14 | > [https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=en) 15 | 16 | 17 | 4. 注册一个钱包, 并登陆钱包. 18 | > [https://www.myetherwallet.com/](https://www.myetherwallet.com/) 19 | 20 | 5. 在meta mask 中添加自定义RPC BSC主网配置 21 | ``` 22 | 1. 网络名称: Binance Smart Chain 23 | 2. 新建 RPC URL: ​https://bsc-dataseed1.binance.org:443​ 24 | 3. ChainID: 56 25 | 4. 符号: BNB 26 | 5. 区块浏览器: ​https://explorer.binance.org/smart 27 | 28 | ``` 29 | 30 | 6. 打开汉堡的地址 31 | > [https://burgerswap.org/](https://burgerswap.org/) 32 | 33 | 7. 从交易所转BNB和USDT等其他代币BEP20的代币, 然后添加流动性挖矿 34 | 35 | ## 注意事项 36 | 1. 记得注册钱包的时候,把注册记录下来,并且备份多个 37 | 2. 转账的时候,记得使用BEP20的网络,否则可能资产丢失。最好小额先测试下. 38 | 3. 目前汉堡目前还没有经过第三方的审计公司进行审核,合约安全性可能有问题。 39 | 4. 注意控制风险. 40 | --------------------------------------------------------------------------------