├── Portfolio_fees.txt ├── BinanceKeys.py ├── Historic-Legacy ├── readme.md ├── Sentiment_Analysis_Crypto_Historic.py ├── CryptoTriangularArbitrageBinanceBot.py ├── Private_TriArbBot.py └── TriArbBot_Paper_and_Tweet.py ├── list_fees_paid.txt ├── LICENSE ├── Stochastic_Crypto_Pandas_Stock.py ├── Portfolio.txt ├── README.md ├── Crypto-Trading-Bots ├── TradingView_SignalScraper.py ├── Roibal_BinanceBot.py ├── Crypto_Sentiment_Analysis_SocialMedia_Bot.py └── Advanced_Cryptocurrency_Trading_Bot.py └── save_historical_data_Roibal.py /Portfolio_fees.txt: -------------------------------------------------------------------------------- 1 | 2 | [10, 5.0, 20.0, 30.0, '2018-11-10 16:42:39.721002'] -------------------------------------------------------------------------------- /BinanceKeys.py: -------------------------------------------------------------------------------- 1 | BinanceKey1 = {'api_key': 'YourApiKey', 2 | 'api_secret':'YourApiSecret'} 3 | -------------------------------------------------------------------------------- /Historic-Legacy/readme.md: -------------------------------------------------------------------------------- 1 | # Historic Legacy Code - Crypto Trading Bots 2 | 3 | This sub-folder was created to store deprecated and historic versions of the crypto trading bots in above folder, in order to keep things cleaner and more organized in both folders. 4 | 5 | These historic legacy bots are kept in order to allow understanding / access of bots at earlier stage of development. 6 | 7 | Please see readme of higher folder for more detailed instructions. 8 | -------------------------------------------------------------------------------- /list_fees_paid.txt: -------------------------------------------------------------------------------- 1 | 2 | [0.014894000000000001, 0.014894000000000001, 7.447000000000001e-06, 0.014886553000000002] 3 | [0.02620872007042254, 0.026221830985915497, 1.3104360035211271e-05, 0.02619561571038733] 4 | [2.216411045255872e-05, 2.2186291197183104e-05, 1.108205522627936e-08, 2.2153028397332442e-05] 5 | [3.299472049498694e-08, 3.299472049498694e-08, 1.649736024749347e-11, 3.2978223134739444e-08] 6 | [5.806025199778072e-08, 5.808929664610377e-08, 2.903012599889036e-11, 5.8031221871781833e-08] 7 | [4.910021682571461e-11, 4.91493538922684e-11, 2.4550108412857306e-14, 4.907566671730175e-11] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Joaquin Roibal 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 | -------------------------------------------------------------------------------- /Stochastic_Crypto_Pandas_Stock.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | The purpose of this software is to format Bitcoin Price and DJIA into a Pandas format 4 | which will then be analyzed using Stochastic methods with TA-Lib 5 | 6 | Created 12/26/2018 7 | 8 | Inspired by Sentdex "Pandas" tutorial 9 | 10 | Copyright 2018 by Joaquin Roibal (@BlockchainEng) 11 | 12 | """ 13 | 14 | import pandas as pd 15 | import datetime 16 | import matplotlib.pyplot as plt 17 | from matplotlib import style 18 | #import talib as ta 19 | import numpy as np 20 | 21 | style.use('ggplot') 22 | 23 | #start = datetime.datetime(2010, 1, 1) 24 | #end = datetime.datetime(2015, 1, 1) 25 | def run(): 26 | #Format 30 Day Historical Data from CoinMarketCap into a Pandas data format 27 | url = 'https://coinmarketcap.com/currencies/bitcoin/historical-data/?start=20180727&end=20181227' 28 | btc90day = pd.read_html(url, header=0) 29 | btc_30_sma = simple_moving_average(btc90day[0]['Close**']) 30 | #btc_30_sma += btc90day[0]['Close**'][0:29] 31 | print(btc_30_sma) 32 | print(btc90day[0].head()) 33 | plt.figure(1) 34 | #plt.subplot(121) 35 | ax = plt.gca() 36 | plt.plot(btc90day[0]['Date'], btc90day[0]['Close**'], label='Bitcoin', color='Black') 37 | plt.plot(btc90day[0]['Date'][:-29], btc_30_sma, label='30 Day BTC SMA', color = 'Red') #Graph 30 day MA, format due to no values for 29 days 38 | plt.title("Bitcoin 6 Month Price at Close\nCopyright 2019 by Joaquin Roibal") 39 | #btc30day[0]['Close**'].plot() 40 | ax.invert_xaxis() 41 | #plt.plot(btc90day[0]['Date'], btc_30_sma, label='30 day SMA') 42 | plt.legend() 43 | #plt.show() 44 | #plt.subplot(122) 45 | #Format Historical Dow Jones Industrial Average into a Pandas format 46 | plt.figure(2) 47 | url2 = "https://finance.yahoo.com/quote/%5EDJI/history/" 48 | DJIA = pd.read_html(url2, header=0) 49 | DJIA[0]=DJIA[0][:-1] 50 | print(DJIA[0]) 51 | DJIA_30_sma = simple_moving_average(DJIA[0]['Close*']) 52 | ax = plt.gca() 53 | plt.title("Dow Jones 90 Day Price at Close\nCopyright 2019 by Joaquin Roibal") 54 | plt.plot(DJIA[0]['Date'], DJIA[0]['Close*'], label='DJIA', color = 'Black') 55 | plt.plot(DJIA[0]['Date'][:-29], DJIA_30_sma, label='DJIA 30 Day SMA', color = 'Red') #Graph 30 day MA, format due to no values for 29 days 56 | ax.invert_xaxis() 57 | #plt.yscale('log') 58 | plt.legend() 59 | plt.show() 60 | 61 | #create 5 year, logarithmic btc data visualization 62 | 63 | urlalltime = "https://coinmarketcap.com/currencies/bitcoin/historical-data/?start=20131227&end=20181227" 64 | btcalltime = pd.read_html(urlalltime, header = 0) 65 | print(btcalltime[0].head()) 66 | #btcalltime[0]['Close**'].plot() 67 | #plt.plot(btcalltime[0]['Date'], btcalltime[0]['Close**']) 68 | #plt.show() 69 | 70 | # Following Code from: https://stackoverflow.com/questions/30261541/slow-stochastic-implementation-in-python-pandas 71 | 72 | def simple_moving_average(prices, period=30): 73 | """ 74 | :param df: pandas dataframe object 75 | :param period: periods for calculating SMA 76 | :return: a pandas series 77 | """ 78 | weights = np.repeat(1.0, period)/period 79 | sma = np.convolve(prices, weights, 'valid') 80 | return sma 81 | 82 | 83 | def fast_stochastic(lowp, highp, closep, period=14, smoothing=3): 84 | """ calculate slow stochastic 85 | Fast stochastic calculation 86 | %K = (Current Close - Lowest Low)/(Highest High - Lowest Low) * 100 87 | %D = 3-day SMA of %K 88 | """ 89 | low_min = pd.rolling_min(lowp, period) 90 | high_max = pd.rolling_max(highp, period) 91 | k_fast = 100 * (closep - low_min)/(high_max - low_min) 92 | k_fast = k_fast.dropna() 93 | d_fast = simple_moving_average(k_fast, smoothing) 94 | return k_fast, d_fast 95 | 96 | 97 | def slow_stochastic(lowp, highp, closep, period=14, smoothing=3): 98 | """ calculate slow stochastic 99 | Slow stochastic calculation 100 | %K = %D of fast stochastic 101 | %D = 3-day SMA of %K 102 | """ 103 | k_fast, d_fast = fast_stochastic(lowp, highp, closep, period=period, smoothing=smoothing) 104 | 105 | # D in fast stochastic is K in slow stochastic 106 | k_slow = d_fast 107 | d_slow = simple_moving_average(k_slow, smoothing) 108 | return k_slow, d_slow 109 | 110 | if __name__ == "__main__": 111 | run() -------------------------------------------------------------------------------- /Portfolio.txt: -------------------------------------------------------------------------------- 1 | [10.0, 100.0, 10000.0, 500.0, '2018-06-22 03:22:55.356762'] 2 | [10.0, 100.0, 10000.0, 500.0, '2018-06-22 03:32:37.701786'] 3 | [10.018066457930999, 100.0, 10000.0, 500.0, '2018-06-22 03:33:06.003425'] 4 | [10.02793930295962, 100.0, 10000.0, 500.0, '2018-06-22 03:33:49.586949'] 5 | [10.028612746493302, 100.0, 10000.0, 500.0, '2018-06-22 03:34:33.172075'] 6 | [10.028612746493302, 100.0, 10000.0, 500.0, '2018-06-22 03:34:49.237039'] 7 | [10.028612746493302, 100.0, 10000.0, 500.0, '2018-06-22 03:35:44.034549'] 8 | [10.046525277513561, 100.0, 10000.0, 500.0, '2018-06-22 03:36:13.407100'] 9 | [10.065845708535937, 100.0, 10000.0, 500.0, '2018-06-22 03:36:56.984278'] 10 | [10.077533136274305, 100.0, 10000.0, 500.0, '2018-06-22 03:37:40.570785'] 11 | [10.089934825478926, 100.0, 10000.0, 500.0, '2018-06-22 03:38:24.159488'] 12 | [10.095541252430012, 100.0, 10000.0, 500.0, '2018-06-22 03:39:07.747515'] 13 | [10.101313178734586, 100.0, 10000.0, 500.0, '2018-06-22 03:40:09.843557'] 14 | [10.123325396149632, 100.0, 10000.0, 500.0, '2018-06-22 03:40:53.425518'] 15 | [10.14072142623232, 100.0, 10000.0, 500.0, '2018-06-22 03:41:37.010298'] 16 | [10.156204111637193, 100.0, 10000.0, 500.0, '2018-06-22 03:42:20.607200'] 17 | [10.170612621808338, 100.0, 10000.0, 500.0, '2018-06-22 03:43:04.506750'] 18 | [10.170612621808338, 100.0, 10000.0, 500.0, '2018-06-22 03:43:39.935353'] 19 | [10.186652302104717, 100.0, 10000.0, 500.0, '2018-06-22 03:44:08.306799'] 20 | [10.196042637421623, 100.0, 10000.0, 500.0, '2018-06-22 03:44:52.200969'] 21 | [10.230338984010656, 100.0, 10000.0, 500.0, '2018-06-22 03:45:36.739709'] 22 | [10.237835771421928, 100.0, 10000.0, 500.0, '2018-06-22 03:46:20.518580'] 23 | [10.265234134183453, 100.0, 10000.0, 500.0, '2018-06-22 03:47:04.106095'] 24 | [10.265234134183453, 100.0, 10011.482826965612, 500.0, '2018-06-22 03:48:03.687608'] 25 | [10.265234134183453, 100.0, 10019.276958222777, 500.0, '2018-06-22 03:48:47.284105'] 26 | [10.265234134183453, 100.0, 10021.826746861203, 500.0, '2018-06-22 03:49:30.870924'] 27 | [10.265234134183453, 100.0, 10021.826746861203, 500.0, '2018-06-22 03:51:34.660780'] 28 | [10.265234134183453, 100.0, 10028.470915457803, 500.0, '2018-06-22 03:52:03.012803'] 29 | [10.265234134183453, 100.0, 10039.965615790552, 500.0, '2018-06-22 03:52:46.589219'] 30 | [10.265234134183453, 100.0, 10058.353792131906, 500.0, '2018-06-22 03:53:31.218212'] 31 | [10.265234134183453, 100.0, 10065.767161614856, 500.0, '2018-06-22 03:54:14.803643'] 32 | [10.265234134183453, 100.0, 10071.369182772647, 500.0, '2018-06-22 03:54:58.397677'] 33 | [10.26846664106059, 100.0, 10071.369182772647, 500.0, '2018-06-22 03:55:57.973720'] 34 | [10.276704286387114, 100.0, 10071.369182772647, 500.0, '2018-06-22 03:56:43.151256'] 35 | [10.292615345399055, 100.0, 10071.369182772647, 500.0, '2018-06-22 03:57:28.888626'] 36 | [10.317426762027647, 100.0, 10071.369182772647, 500.0, '2018-06-22 03:58:14.888802'] 37 | [10.327305712366043, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:00:00.549310'] 38 | [10.348482559416038, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:00:46.229204'] 39 | [10.360005699727058, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:01:31.894953'] 40 | [10.363303272431931, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:02:17.328901'] 41 | [10.38771629925594, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:03:01.736835'] 42 | [10.411889331083227, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:04:10.506883'] 43 | [10.428681689524332, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:04:56.403583'] 44 | [10.438628566485177, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:05:42.494176'] 45 | [10.447733600487705, 100.0, 10071.369182772647, 500.0, '2018-06-22 04:06:28.801141'] 46 | [10.447733600487705, 100.0, 10073.224267341895, 500.0, '2018-06-22 04:08:13.542926'] 47 | [10.447733600487705, 100.0, 10089.588548886013, 500.0, '2018-06-22 04:08:57.123847'] 48 | [10.447733600487705, 100.0, 10108.31056859837, 500.0, '2018-06-22 04:09:40.743826'] 49 | [10.447733600487705, 100.0, 10108.31056859837, 500.0, '2018-06-22 11:51:48.561739'] 50 | [10.447733600487705, 100.0, 10119.633082247987, 500.0, '2018-06-22 11:52:16.668652'] 51 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-06-22 11:53:00.217573'] 52 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-10 17:04:18.185724'] 53 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-10 17:05:11.552163'] 54 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-10 17:41:15.635595'] 55 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-10 18:38:38.129955'] 56 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-10 20:32:44.589157'] 57 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-10 22:10:48.054281'] 58 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 11:17:16.345545'] 59 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 11:32:05.450407'] 60 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 14:45:37.577880'] 61 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 15:46:51.420157'] 62 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 18:22:58.244914'] 63 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 18:30:24.713100'] 64 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 18:31:22.476606'] 65 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 18:54:05.073653'] 66 | [10.447733600487705, 100.0, 10123.326275380954, 500.0, '2018-11-11 19:01:09.588442'] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cryptocurrency / Bitcoin Trading Bots in Python 2 | 3 | ## Algo / Automated Cryptocurrency Trading with Python-Based Open Source Software 4 | 5 | ## Guides and Instructional YouTube Videos by @BlockchainEng Joaquin Roibal focusing on crypto trading strategies such as Triangular Arbitrage, Market Making, etc. 6 | 7 | Hello and welcome to the code repository of @BlockchainEng Joaquin Roibal. 8 | 9 | This Github Repository is used as a collection of python codes that you may find useful for **making your own cryptocurrency trading bots or applying advanced trading strategies (Triangular Arbitrage, Market Making) to the cryptocurrency markets.** Among other useful tools. 10 | 11 | You may want to begin by watching my youtube video channel on introduction to crypto bot trading or advanced strategies such as triangular arbitrage, which will help you to understand the purpose and reasoning behind the code in this repo. 12 | 13 | CRYPTO TRADING BOT VIDEOS: https://www.youtube.com/channel/UCVTnyT4fUxYkvawbggo8-AQ 14 | 15 | ## Getting Started with Crypto Trading Bot Software 16 | 17 | The purpose of these bots is to implement an advanced strategy of cryptocurrency trading on a cryptocurrency exchange, such as Binance. You will need a computer, a binance account, and a copy of this code. You will be able to run this bot as a software to make profitable trades for you. 18 | 19 | ## Blockchain Engineer Crypto Trading Bot Python Binance Code 20 | 21 | --- 22 | TO SUPPORT THIS PROJECT SEND BTC: 1BYrAED4pi5DMKu2qZPv8pwe6rEeuxoCiD 23 | --- 24 | 25 | This Portfolio contains Beginner & Advanced Cryptocurrency Trading Bots Written in Python. You are most likely interested in one of three main files/implementations of particular strategies: 26 | 27 | **Triangular Arbitrage - Crypto_Triangular_Arbitrage_Bot.py** is the newest form of the crypto triangular arbitrage bots, and has all functionality to trade and output results via twitter. (Read More: https://medium.com/@BlockchainEng/triangular-arbitrage-with-cryptocurrency-on-binance-exchange-with-python-videos-and-code-real-bc63d0905d05 ) **NOTE: This is the most up to date tri arb code available; Historic versions available in Historic-Legacy folder.** 28 | 29 | **Beginner - RoibalBot_BinanceBot.py** (converted from original - Roibal Bot) ([Read More About Binance Trading Bot Here:](https://medium.com/@BlockchainEng/how-to-build-an-automated-cryptocurrency-trading-bot-on-binance-with-python-2cd9b5874e44) ) 30 | 31 | **Advanced - AdvancedCryptocurrencyTradingBot.py** (converted from RoibalBot_BinanceBot.py) ([Read More About Advanced Cryptocurrency Trading Bot Course Here:](https://medium.com/@BlockchainEng/advanced-cryptocurrency-trading-bot-python-open-source-chapters-5-6-7-72b36b378750) ) 32 | 33 | ## Online Cryptocurrency Trading Bot Resources 34 | 35 | To help you to learn to **implement this code as a profitable crypto trader**, I have many online resources available. For example: 36 | 37 | 1. Youtube Channel coverying Crypto Trading Bot Tutorial Videos: https://www.youtube.com/channel/UCVTnyT4fUxYkvawbggo8-AQ 38 | 2. Medium (Blog) about crypto trading bots: https://www.medium.com/@BlockchainEng 39 | 3. Twitter: http://www.twitter.com/BlockchainEng 40 | 4. Email: realestateblockchain1@gmail.com 41 | 6. Chat Directly Via Telegram: https://t.me/BlockchainEng 42 | 7. Bitcoin Trading Bot Software Telegram Group: https://t.co/YlGP1zvvw4 43 | 8. LinkedIn: https://www.linkedin.com/in/joaquinroibal/ 44 | 9. Cryptocurrency Trading Software LinkedIn Group: https://www.linkedin.com/groups/12121918 45 | 10. Crypto Bot Professionals For Hire: www.bot-professionals.com 46 | 47 | 48 | ## Historic - Legacy Folder 49 | 50 | **The Historic-Legacy Folder** contains previous/out-dated copies of the bots that are located within this folder, you may be interested to develop from an earlier point, or edit before a certain modification to the code was made. 51 | 52 | 53 | ### Installing and Running Crypto Trading Bot - Crypto Triangular Arbitrage, Basic Bitcoin Bot 54 | 55 | **STEP BY STEP TUTORIAL OF INSTALLATION AVAILABLE ON YOUTUBE HERE:** https://www.youtube.com/watch?v=u7ZOQar5V7w 56 | 57 | git clone https://github.com/Roibal/Cryptocurrency-Trading-Bots-Python-Beginner-Advance.git 58 | 59 | git clone https://github.com/Roibal/python-binance.git 60 | 61 | pip install ccxt 62 | 63 | place desired bot (Roibal_BinanceBot.py, Private_TriArbBot.py) in python-binance/examples folder 64 | 65 | then in your console, type **python Roibal_BinanceBot.py** or load in your favorite python IDE (such as Pycharm) 66 | 67 | https://www.youtube.com/watch?v=Y4RwD1OGz4c 68 | 69 | To run any of these bots, first download the Roibal fork of 'Python-Binance', install or unzip this code on your computer. Then place whatever bot from this folder (RoibalBot.py) in the Python-Binance/Examples folder and run/edit that file with whatever python IDE you would like. For the more advanced bots you will need to install CCXT (can be installed via pip or pycharm install). 70 | 71 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system. 72 | 73 | https://www.youtube.com/watch?v=8AAN03M8QhA 74 | 75 | Visualization of Order Book and Scalping Functionality: https://youtu.be/zslp0FA_Nkw 76 | 77 | ## Authors 78 | 79 | * Joaquin Roibal (@BlockchainEng) 80 | 81 | See also the list of [contributors](https://github.com/Roibal/Cryptocurrency-Trading-Bots-Python-Beginner-Advance/graphs/contributors) who participated in this project. 82 | 83 | ## License 84 | 85 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 86 | 87 | ## Acknowledgments 88 | 89 | * For Readme Format: Billie Thompson - [PurpleBooth](https://github.com/PurpleBooth) 90 | * Python-Binance 91 | * CCTX 92 | 93 | **USE AT YOUR OWN RISK - NOT RESPONSIBLE FOR ANY FINANCIAL LOSSES YOU MAY INCUR** 94 | -------------------------------------------------------------------------------- /Historic-Legacy/Sentiment_Analysis_Crypto_Historic.py: -------------------------------------------------------------------------------- 1 | """ 2 | Twitter Sentiment Analysis in Python - A bot which will monitor, store and categorize Sentiment Analysis based on Twitter 3 | for cryptocurrencies, and implement a strategy for profitable trading based on Bitcoin Barbie Bot (BBB) Strategy, described here: 4 | 5 | https://medium.com/@BlockchainEng/crypto-trading-bot-sentiment-analysis-bot-bfbd8dd1df5a 6 | 7 | Youtube Series Here: 8 | 6/30/2018 9 | 10 | @BlockchainEng 11 | Copyright 2018 - All Rights Reserved 12 | """ 13 | 14 | def run(): 15 | #This Bot is to perform sentiment analysis, then implement a trade strategy based on sentiment and price 16 | """ 17 | Monitor, collect and save tweets mentioning Cryptocurrency Y in file format. 18 | Perform Sentiment Analysis on a historic data set, and recent tweets during a specified time period (1 hour, 5 minutes, 1 day). Track and record historical values in file format. Visualize data through python script. 19 | Trade structure attempting to mimic this strategy: 20 | If Sentiment positive (‘buy’) and green candle (‘higher price’), wait to purchase coins. 21 | If candle decreases 2% (or more) in specified time period (5 minutes, 1 hour, 1 day), Purchase quantity of coin. 22 | Sell when price increases 5% (adjustable). 23 | To Reiterate, the functionality of of a bot to implement this strategy is based on a python script that will: 24 | 25 | Monitor all tweets mentioning X-Coin, perform sentiment analysis to determine buy/sell signalling from crypto-accounts 26 | Track Historical Values in CSV spreadsheet format 27 | Compare current/recent values to historic values 28 | Tweet out ‘Alerts’ based on strategy, and perform successful trades on Binance 29 | 30 | :return: 31 | """ 32 | #Instructions: https://www.geeksforgeeks.org/twitter-sentiment-analysis-using-python/ 33 | import tweepy 34 | import textblob 35 | 36 | textblob.download_corpora 37 | 38 | import re 39 | import tweepy 40 | from tweepy import OAuthHandler 41 | from textblob import TextBlob 42 | 43 | class TwitterClient(object): 44 | ''' 45 | Generic Twitter Class for sentiment analysis. 46 | ''' 47 | def __init__(self): 48 | ''' 49 | Class constructor or initialization method. 50 | ''' 51 | # keys and tokens from the Twitter Dev Console 52 | consumer_key = 'XXXXXXXXXXXXXXXXXXXXXXXX' 53 | consumer_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX' 54 | access_token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX' 55 | access_token_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXX' 56 | 57 | # attempt authentication 58 | try: 59 | # create OAuthHandler object 60 | self.auth = OAuthHandler(consumer_key, consumer_secret) 61 | # set access token and secret 62 | self.auth.set_access_token(access_token, access_token_secret) 63 | # create tweepy API object to fetch tweets 64 | self.api = tweepy.API(self.auth) 65 | except: 66 | print("Error: Authentication Failed") 67 | 68 | def clean_tweet(self, tweet): 69 | ''' 70 | Utility function to clean tweet text by removing links, special characters 71 | using simple regex statements. 72 | ''' 73 | return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t]) 74 | |(\w+:\/\/\S+)", " ", tweet).split()) 75 | 76 | def get_tweet_sentiment(self, tweet): 77 | ''' 78 | Utility function to classify sentiment of passed tweet 79 | using textblob's sentiment method 80 | ''' 81 | # create TextBlob object of passed tweet text 82 | analysis = TextBlob(self.clean_tweet(tweet)) 83 | # set sentiment 84 | if analysis.sentiment.polarity > 0: 85 | return 'positive' 86 | elif analysis.sentiment.polarity == 0: 87 | return 'neutral' 88 | else: 89 | return 'negative' 90 | 91 | def get_tweets(self, query, count = 10): 92 | ''' 93 | Main function to fetch tweets and parse them. 94 | ''' 95 | # empty list to store parsed tweets 96 | tweets = [] 97 | 98 | try: 99 | # call twitter api to fetch tweets 100 | fetched_tweets = self.api.search(q = query, count = count) 101 | 102 | # parsing tweets one by one 103 | for tweet in fetched_tweets: 104 | # empty dictionary to store required params of a tweet 105 | parsed_tweet = {} 106 | 107 | # saving text of tweet 108 | parsed_tweet['text'] = tweet.text 109 | # saving sentiment of tweet 110 | parsed_tweet['sentiment'] = self.get_tweet_sentiment(tweet.text) 111 | 112 | # appending parsed tweet to tweets list 113 | if tweet.retweet_count > 0: 114 | # if tweet has retweets, ensure that it is appended only once 115 | if parsed_tweet not in tweets: 116 | tweets.append(parsed_tweet) 117 | else: 118 | tweets.append(parsed_tweet) 119 | 120 | # return parsed tweets 121 | return tweets 122 | 123 | except tweepy.TweepError as e: 124 | # print error (if any) 125 | print("Error : " + str(e)) 126 | 127 | def main(): 128 | # creating object of TwitterClient Class 129 | api = TwitterClient() 130 | # calling function to get tweets 131 | tweets = api.get_tweets(query = 'Donald Trump', count = 200) 132 | 133 | # picking positive tweets from tweets 134 | ptweets = [tweet for tweet in tweets if tweet['sentiment'] == 'positive'] 135 | # percentage of positive tweets 136 | print("Positive tweets percentage: {} %".format(100*len(ptweets)/len(tweets))) 137 | # picking negative tweets from tweets 138 | ntweets = [tweet for tweet in tweets if tweet['sentiment'] == 'negative'] 139 | # percentage of negative tweets 140 | print("Negative tweets percentage: {} %".format(100*len(ntweets)/len(tweets))) 141 | # percentage of neutral tweets 142 | print("Neutral tweets percentage: {} % \ 143 | ".format(100*len(tweets - ntweets - ptweets)/len(tweets))) 144 | 145 | # printing first 5 positive tweets 146 | print("\n\nPositive tweets:") 147 | for tweet in ptweets[:10]: 148 | print(tweet['text']) 149 | 150 | # printing first 5 negative tweets 151 | print("\n\nNegative tweets:") 152 | for tweet in ntweets[:10]: 153 | print(tweet['text']) 154 | 155 | if __name__ == "__main__": 156 | # calling main function 157 | main() 158 | -------------------------------------------------------------------------------- /Crypto-Trading-Bots/TradingView_SignalScraper.py: -------------------------------------------------------------------------------- 1 | """ 2 | A python script/bot which will collect (scrape) TradingView Signals for a list of coins. 3 | Original Code by Michael Goode 4 | Modified 7/15/2018 by Joaquin Roibal (@BlockchainEng) 5 | 6 | """ 7 | 8 | import requests, json, time, datetime 9 | from BinanceKeys import BinanceKey1 10 | import tweepy 11 | from samplekeys import keys, keys2, keys3, rkey 12 | 13 | api_key = BinanceKey1['api_key'] 14 | api_secret = BinanceKey1['api_secret'] 15 | #load twitter instantiating code 16 | list_of_accts = [keys, keys2, keys3] 17 | #Oauth consumer key/secret and token/secret from twitter application 18 | consumer_key = keys3['consumer_key'] 19 | consumer_secret = keys3['consumer_secret'] 20 | 21 | access_token = keys3['access_token'] 22 | access_token_secret = keys3['access_token_secret'] 23 | 24 | #Authorization for Tweepy format 25 | auth = tweepy.OAuthHandler(consumer_key, consumer_secret) 26 | auth.set_access_token(access_token, access_token_secret) 27 | api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) 28 | 29 | 30 | def mlog(market, *text): 31 | text = [str(i) for i in text] 32 | text = " ".join(text) 33 | 34 | datestamp = str(datetime.datetime.now().strftime("%H:%M:%S.%f")[:-3]) 35 | 36 | print("[{} {}] - {}".format(datestamp, market, text)) 37 | 38 | 39 | def get_signal(market, candle): 40 | headers = {'User-Agent': 'Mozilla/5.0'} 41 | url = "https://scanner.tradingview.com/crypto/scan" 42 | 43 | payload = { 44 | "symbols": { 45 | "tickers": ["BINANCE:{}".format(market)], 46 | "query": { "types": [] } 47 | }, 48 | "columns": [ 49 | "Recommend.Other|{}".format(candle), 50 | "Recommend.All|{}".format(candle), 51 | "Recommend.MA|{}".format(candle), 52 | "RSI|{}".format(candle), 53 | "RSI[1]|{}".format(candle), 54 | "Stoch.K|{}".format(candle), 55 | "Stoch.D|{}".format(candle), 56 | "Stoch.K[1]|{}".format(candle), 57 | "Stoch.D[1]|{}".format(candle), 58 | "CCI20|{}".format(candle), 59 | "CCI20[1]|{}".format(candle), 60 | "ADX|{}".format(candle), 61 | "ADX+DI|{}".format(candle), 62 | "ADX-DI|{}".format(candle), 63 | "ADX+DI[1]|{}".format(candle), 64 | "ADX-DI[1]|{}".format(candle), 65 | "AO|{}".format(candle), 66 | "AO[1]|{}".format(candle), 67 | "Mom|{}".format(candle), 68 | "Mom[1]|{}".format(candle), 69 | "MACD.macd|{}".format(candle), 70 | "MACD.signal|{}".format(candle), 71 | "Rec.Stoch.RSI|{}".format(candle), 72 | "Stoch.RSI.K|{}".format(candle), 73 | "Rec.WR|{}".format(candle), 74 | "W.R|{}".format(candle), 75 | "Rec.BBPower|{}".format(candle), 76 | "BBPower|{}".format(candle), 77 | "Rec.UO|{}".format(candle), 78 | "UO|{}".format(candle), 79 | "EMA10|{}".format(candle), 80 | "close|{}".format(candle), 81 | "SMA10|{}".format(candle), 82 | "EMA20|{}".format(candle), 83 | "SMA20|{}".format(candle), 84 | "EMA30|{}".format(candle), 85 | "SMA30|{}".format(candle), 86 | "EMA50|{}".format(candle), 87 | "SMA50|{}".format(candle), 88 | "EMA100|{}".format(candle), 89 | "SMA100|{}".format(candle), 90 | "EMA200|{}".format(candle), 91 | "SMA200|{}".format(candle), 92 | "Rec.Ichimoku|{}".format(candle), 93 | "Ichimoku.BLine|{}".format(candle), 94 | "Rec.VWMA|{}".format(candle), 95 | "VWMA|{}".format(candle), 96 | "Rec.HullMA9|{}".format(candle), 97 | "HullMA9|{}".format(candle), 98 | "Pivot.M.Classic.S3|{}".format(candle), 99 | "Pivot.M.Classic.S2|{}".format(candle), 100 | "Pivot.M.Classic.S1|{}".format(candle), 101 | "Pivot.M.Classic.Middle|{}".format(candle), 102 | "Pivot.M.Classic.R1|{}".format(candle), 103 | "Pivot.M.Classic.R2|{}".format(candle), 104 | "Pivot.M.Classic.R3|{}".format(candle), 105 | "Pivot.M.Fibonacci.S3|{}".format(candle), 106 | "Pivot.M.Fibonacci.S2|{}".format(candle), 107 | "Pivot.M.Fibonacci.S1|{}".format(candle), 108 | "Pivot.M.Fibonacci.Middle|{}".format(candle), 109 | "Pivot.M.Fibonacci.R1|{}".format(candle), 110 | "Pivot.M.Fibonacci.R2|{}".format(candle), 111 | "Pivot.M.Fibonacci.R3|{}".format(candle), 112 | "Pivot.M.Camarilla.S3|{}".format(candle), 113 | "Pivot.M.Camarilla.S2|{}".format(candle), 114 | "Pivot.M.Camarilla.S1|{}".format(candle), 115 | "Pivot.M.Camarilla.Middle|{}".format(candle), 116 | "Pivot.M.Camarilla.R1|{}".format(candle), 117 | "Pivot.M.Camarilla.R2|{}".format(candle), 118 | "Pivot.M.Camarilla.R3|{}".format(candle), 119 | "Pivot.M.Woodie.S3|{}".format(candle), 120 | "Pivot.M.Woodie.S2|{}".format(candle), 121 | "Pivot.M.Woodie.S1|{}".format(candle), 122 | "Pivot.M.Woodie.Middle|{}".format(candle), 123 | "Pivot.M.Woodie.R1|{}".format(candle), 124 | "Pivot.M.Woodie.R2|{}".format(candle), 125 | "Pivot.M.Woodie.R3|{}".format(candle), 126 | "Pivot.M.Demark.S1|{}".format(candle), 127 | "Pivot.M.Demark.Middle|{}".format(candle), 128 | "Pivot.M.Demark.R1|{}".format(candle) 129 | ] 130 | } 131 | 132 | resp = requests.post(url,headers=headers,data=json.dumps(payload)).json() 133 | signal = oscillator = resp["data"][0]["d"][1] 134 | 135 | return signal 136 | def run(): 137 | while 1: 138 | market_list = ["BTCUSDT", "BNBETH", "ICXBTC", "WTCBTC", "XEMETH", "NEOBTC", "NANOUSD", "GTOETH", "RPXETH", "HSRETH", "CDTETH"] 139 | candle_list = [5, 60, 240] #Represented in minutes 140 | signals_list = [] 141 | for candle in candle_list: 142 | signal1 = [] 143 | msg = "Crypto Buy/Sell Signals from @tradingview - {} min candle\n\n".format(candle) 144 | for market in market_list: 145 | mlog(market, "{}, {} minute candle. TradingView".format(market, candle)) 146 | signal = round(get_signal(market, candle),3) 147 | signal1.append(signal) 148 | msg += "{} {} : ".format(market, signal) 149 | if signal>0.5: 150 | msg+= "STRONG BUY\n" 151 | elif signal>0: 152 | msg+= "BUY\n" 153 | elif signal>-0.5: 154 | msg+= "SELL\n" 155 | else: 156 | msg+= "STRONG SELL\n" 157 | mlog(market, signal) 158 | signals_list.append(signal1) 159 | tweet(msg) 160 | save_signals(market_list, candle_list, signals_list) 161 | 162 | time.sleep(60*5) 163 | 164 | def save_signals(market_list, candle_list, signals_list): 165 | with open("SignalsFile.csv", "a") as f1: 166 | f1.writelines("\n"+str(datetime.datetime.now())+"\n") 167 | #Format Output to be easily loaded into Microsoft Excel 168 | """for ex in ['[', ']']: 169 | for ex1 in [market_list, candle_list, signals_list]: 170 | ex1.strip(ex) 171 | for coin in market_list: 172 | for candle in candle_list: 173 | """ 174 | 175 | f1.writelines(str(market_list)+"\n") 176 | #f1.writelines(str(candle_list)+"\n") 177 | for lines in signals_list: 178 | f1.writelines(str(lines)+"\n") 179 | 180 | 181 | def tweet(msg): 182 | msg+= "\n" #+ str(start_time)+ " - " +str(end_time) 183 | msg+="\n\nvia @BlockchainEng \n\n #Bitcoin #BTC #Crypto #BitcoinTrading #CryptoTrading #CryptoTradingBot" 184 | print(msg) #Tweet this message then upload file 185 | if len(msg)>279: 186 | msg = msg[0:279] 187 | #api.update_status(msg) 188 | 189 | if __name__ == "__main__": 190 | run() 191 | -------------------------------------------------------------------------------- /save_historical_data_Roibal.py: -------------------------------------------------------------------------------- 1 | import time 2 | import dateparser 3 | import pytz 4 | import json 5 | import matplotlib 6 | import matplotlib.pyplot as plt 7 | import matplotlib.ticker as mticker 8 | import matplotlib.dates as mdates 9 | import mpl_finance #import candlestick_ohlc 10 | 11 | from datetime import datetime 12 | from binance.client import Client 13 | from BinanceKeys import BinanceKey1 14 | 15 | 16 | api_key = BinanceKey1['api_key'] 17 | api_secret = BinanceKey1['api_secret'] 18 | 19 | client = Client(api_key, api_secret) 20 | list_of_symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT','BNBBTC', 'ETHBTC', 'LTCBTC'] 21 | 22 | 23 | def run(): 24 | # get system status 25 | #client.ping() 26 | status = client.get_system_status() 27 | print("\nExchange Status: ", status) 28 | 29 | #Account Withdrawal History Info 30 | withdraws = client.get_withdraw_history() 31 | print("\nClient Withdraw History: ", withdraws) 32 | 33 | #get Exchange Info 34 | info = client.get_exchange_info() 35 | print("\nExchange Info (Limits): ", info) 36 | 37 | # place a test market buy order, to place an actual order use the create_order function 38 | # if '1000 ms ahead of server time' error encountered, visit https://github.com/sammchardy/python-binance/issues/249 39 | """order = client.create_test_order( 40 | symbol='BNBBTC', 41 | side=Client.SIDE_BUY, 42 | type=Client.ORDER_TYPE_MARKET, 43 | quantity=100)""" 44 | 45 | coin_prices(list_of_symbols) 46 | coin_tickers(list_of_symbols) 47 | for symbol in list_of_symbols: 48 | market_depth(symbol) 49 | 50 | #save_historic_klines_datafile("ETHBTC", "1 Dec, 2017", "1 Jan, 2018", Client.KLINE_INTERVAL_30MINUTE) 51 | 52 | #save_historic_klines_datafile("BTCUSDT", "12 hours ago UTC", "Now UTC", Client.KLINE_INTERVAL_1MINUTE) 53 | 54 | def market_depth(sym, num_entries=10): 55 | #Get market depth 56 | #Retrieve and format market depth (order book) including time-stamp 57 | i=0 #Used as a counter for number of entries 58 | print("Order Book: ", convert_time_binance(client.get_server_time())) 59 | depth = client.get_order_book(symbol=sym) 60 | print("\n", sym, "\nDepth ASKS:\n") 61 | print("Price Amount") 62 | for ask in depth['asks']: 63 | if i2: 270 | price3=0 271 | for pri in list_of_open[-3:]: 272 | price3+=pri 273 | three_period_moving_ave.append(float(price3/3)) 274 | time3.append(time1) 275 | #Perform Moving Average Calculation for 10 periods 276 | if len(list_of_open)>9: 277 | price10=0 278 | for pri in list_of_open[-10:]: 279 | price10+=pri 280 | ten_period_moving_ave.append(float(price10/10)) 281 | time10.append(time1) 282 | 283 | #Matplotlib visualization how-to from: https://pythonprogramming.net/candlestick-ohlc-graph-matplotlib-tutorial/ 284 | fig, ax = plt.subplots() 285 | mpl_finance.candlestick_ochl(ax, ochl, width=1) 286 | plt.plot(time3, three_period_moving_ave, color='green', label='3 Period MA - Open') 287 | plt.plot(time10, ten_period_moving_ave, color='blue', label='10 Period MA - Open') 288 | #ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d-%h-%m')) #Converting to date format not working 289 | ax.set(xlabel='Date', ylabel='Price', title='{} {}-{}'.format(symbol, start, end)) 290 | plt.legend() 291 | plt.show() 292 | 293 | def save_historic_klines_datafile(symbol, start, end, interval): 294 | #Collects kline historical data , output and saves to file 295 | klines = get_historical_klines(symbol, interval, start, end) 296 | 297 | # open a file with filename including symbol, interval and start and end converted to milliseconds 298 | with open( 299 | "Binance_{}_{}_{}-{}_{}-{}.json".format( 300 | symbol, 301 | interval, 302 | start, 303 | end, 304 | date_to_milliseconds(start), 305 | date_to_milliseconds(end) 306 | ), 307 | 'w' # set file write mode 308 | ) as f: 309 | f.write(json.dumps(klines)) 310 | 311 | if __name__ == "__main__": 312 | run() 313 | -------------------------------------------------------------------------------- /Crypto-Trading-Bots/Roibal_BinanceBot.py: -------------------------------------------------------------------------------- 1 | """ 2 | The Purpose of the RoibalBot Python Program is to create an automated trading bot (functionality) on Binance 3 | Utilized Python-Binance ( https://github.com/sammchardy/python-binance ) 4 | Advanced-Version capable of all exchanges, all coins (using cctx) 5 | 6 | Created 4/14/2018 by Joaquin Roibal 7 | V 0.01 - Updated 4/20/2018 8 | v 0.02 - Updated 5/30/2018 - Converted to Advanced Version: https://github.com/Roibal/Cryptocurrency-Trading-Bots-Python-Beginner-Advance 9 | 10 | Licensed under MIT License 11 | 12 | Instructional Youtube Video: https://www.youtube.com/watch?v=8AAN03M8QhA 13 | 14 | Did you enjoy the functionality of this bot? Tips always appreciated. 15 | 16 | BTC: 17 | ETH: 18 | 19 | NOTE: All Subsequent Version of Program must contain this message, unmodified, in it's entirety 20 | Copyright (c) 2018 by Joaquin Roibal 21 | """ 22 | 23 | from binance.client import Client 24 | import time 25 | import matplotlib 26 | from matplotlib import cm 27 | import matplotlib.pyplot as plt 28 | from binance.enums import * 29 | import save_historical_data_Roibal 30 | from BinanceKeys import BinanceKey1 31 | 32 | api_key = BinanceKey1['api_key'] 33 | api_secret = BinanceKey1['api_secret'] 34 | 35 | client = Client(api_key, api_secret) 36 | 37 | # get a deposit address for BTC 38 | address = client.get_deposit_address(asset='BTC') 39 | 40 | def run(): 41 | # get system status 42 | #Create List of Crypto Pairs to Watch 43 | list_of_symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT','BNBBTC', 'ETHBTC', 'LTCBTC'] 44 | micro_cap_coins = ['ICXBNB', 'BRDBNB', 'NAVBNB', 'RCNBNB'] 45 | #time_horizon = "Short" 46 | #Risk = "High" 47 | print("\n\n---------------------------------------------------------\n\n") 48 | print("Hello and Welcome to the Crypto Trader Bot Python Script\nCreated 2018 by Joaquin Roibal (@BlockchainEng)") 49 | print("A quick 'run-through' will be performed to introduce you to the functionality of this bot") 50 | print("To learn more visit medium.com/@BlockchainEng or watch introductory Youtube Videos") 51 | time.sleep(5) 52 | try: 53 | #Example Visualizations of Coins 54 | save_historical_data_Roibal.save_historic_klines_csv('BTCUSDT', "1 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_1MINUTE) 55 | save_historical_data_Roibal.save_historic_klines_csv('ETHBTC', "6 months ago UTC", "now UTC", Client.KLINE_INTERVAL_1DAY) 56 | save_historical_data_Roibal.save_historic_klines_csv('BRDBNB', "8 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_3MINUTE) 57 | save_historical_data_Roibal.save_historic_klines_csv('BTCUSDT', "12 months ago UTC", "now UTC", Client.KLINE_INTERVAL_1WEEK) 58 | save_historical_data_Roibal.save_historic_klines_csv('ETHUSDT', "8 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_15MINUTE) 59 | 60 | #Visualize All Micro Cap Coins for 8 hour period and 3 minute Candlestick 61 | for coin in micro_cap_coins: 62 | save_historical_data_Roibal.save_historic_klines_csv(coin, "8 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_3MINUTE) 63 | save_historical_data_Roibal.save_historic_klines_csv(coin, "24 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_15MINUTE) 64 | save_historical_data_Roibal.save_historic_klines_csv(coin, "1 month ago UTC", "now UTC", Client.KLINE_INTERVAL_1DAY) 65 | 66 | except(): 67 | pass 68 | #Get Status of Exchange & Account 69 | try: 70 | status = client.get_system_status() 71 | print("\nExchange Status: ", status) 72 | 73 | #Account Withdrawal History Info 74 | withdraws = client.get_withdraw_history() 75 | print("\nClient Withdraw History: ", withdraws) 76 | 77 | #get Exchange Info 78 | info = client.get_exchange_info() 79 | print("\nExchange Info (Limits): ", info) 80 | except(): 81 | pass 82 | 83 | # place a test market buy order, to place an actual order use the create_order function 84 | # if '1000 ms ahead of server time' error encountered, visit https://github.com/sammchardy/python-binance/issues/249 85 | try: 86 | order = client.create_test_order( 87 | symbol='BNBBTC', 88 | side=Client.SIDE_BUY, 89 | type=Client.ORDER_TYPE_MARKET, 90 | quantity=100) 91 | except: 92 | print("\n \n \nATTENTION: NON-VALID CONNECTION WITH BINANCE \n \n \n") 93 | 94 | #Get Info about Coins in Watch List 95 | coin_prices(list_of_symbols) 96 | coin_tickers(list_of_symbols) 97 | #for symbol in list_of_symbols: 98 | # market_depth(symbol) 99 | 100 | #for coin in micro_cap_coins: 101 | # visualize_market_depth(1, 1, coin) 102 | for coin in micro_cap_coins: 103 | scalping_orders(coin, 1, 1) 104 | 105 | #get recent trades 106 | trades = client.get_recent_trades(symbol='BNBBTC') 107 | print("\nRecent Trades: ", trades) 108 | print("Local Time: ", time.localtime()) 109 | print("Recent Trades Time: ", convert_time_binance(trades[0]['time'])) 110 | 111 | #get historical trades 112 | try: 113 | hist_trades = client.get_historical_trades(symbol='BNBBTC') 114 | print("\nHistorical Trades: ", hist_trades) 115 | except: 116 | print('\n \n \nATTENTION: NON VALID CONNECTION WITH BINANCE \n \n \n') 117 | 118 | #get aggregate trades 119 | agg_trades = client.get_aggregate_trades(symbol='BNBBTC') 120 | print("\nAggregate Trades: ", agg_trades) 121 | 122 | 123 | def convert_time_binance(gt): 124 | #Converts from Binance Time Format (milliseconds) to time-struct 125 | #From Binance-Trader Comment Section Code 126 | #gt = client.get_server_time() 127 | print("Binance Time: ", gt) 128 | print(time.localtime()) 129 | aa = str(gt) 130 | bb = aa.replace("{'serverTime': ","") 131 | aa = bb.replace("}","") 132 | gg=int(aa) 133 | ff=gg-10799260 134 | uu=ff/1000 135 | yy=int(uu) 136 | tt=time.localtime(yy) 137 | #print(tt) 138 | return tt 139 | 140 | 141 | def market_depth(sym, num_entries=20): 142 | #Get market depth 143 | #Retrieve and format market depth (order book) including time-stamp 144 | i=0 #Used as a counter for number of entries 145 | print("Order Book: ", convert_time_binance(client.get_server_time())) 146 | depth = client.get_order_book(symbol=sym) 147 | print(depth) 148 | print(depth['asks'][0]) 149 | ask_tot=0.0 150 | ask_price =[] 151 | ask_quantity = [] 152 | bid_price = [] 153 | bid_quantity = [] 154 | bid_tot = 0.0 155 | place_order_ask_price = 0 156 | place_order_bid_price = 0 157 | max_order_ask = 0 158 | max_order_bid = 0 159 | print("\n", sym, "\nDepth ASKS:\n") 160 | print("Price Amount") 161 | for ask in depth['asks']: 162 | if ifloat(max_order_ask): 164 | #Determine Price to place ask order based on highest volume 165 | max_order_ask=ask[1] 166 | place_order_ask_price=round(float(ask[0]),5)-0.0001 167 | #ask_list.append([ask[0], ask[1]]) 168 | ask_price.append(float(ask[0])) 169 | ask_tot+=float(ask[1]) 170 | ask_quantity.append(ask_tot) 171 | #print(ask) 172 | i+=1 173 | j=0 #Secondary Counter for Bids 174 | print("\n", sym, "\nDepth BIDS:\n") 175 | print("Price Amount") 176 | for bid in depth['bids']: 177 | if jfloat(max_order_bid): 179 | #Determine Price to place ask order based on highest volume 180 | max_order_bid=bid[1] 181 | place_order_bid_price=round(float(bid[0]),5)+0.0001 182 | bid_price.append(float(bid[0])) 183 | bid_tot += float(bid[1]) 184 | bid_quantity.append(bid_tot) 185 | #print(bid) 186 | j+=1 187 | return ask_price, ask_quantity, bid_price, bid_quantity, place_order_ask_price, place_order_bid_price 188 | #Plot Data 189 | 190 | def scalping_orders(coin, wait=1, tot_time=1): 191 | #Function for placing 'scalp orders' 192 | #Calls on Visualizing Scalping Orders Function 193 | ap, aq, bp, bq, place_ask_order, place_bid_order, spread, proj_spread, max_bid, min_ask = visualize_market_depth(wait, tot_time, coin) 194 | print("Coin: {}\nPrice to Place Ask Order: {}\nPrice to place Bid Order: {}".format(coin, place_ask_order, place_bid_order)) 195 | print("Spread: {} % Projected Spread {} %".format(spread, proj_spread)) 196 | print("Max Bid: {} Min Ask: {}".format(max_bid, min_ask)) 197 | #Place Orders based on calculated bid-ask orders if projected > 0.05% (transaction fee) 198 | #Documentation: http://python-binance.readthedocs.io/en/latest/account.html#orders 199 | """ 200 | if proj_spread > 0.05: 201 | quant1=100 #Determine Code Required to calculate 'minimum' quantity 202 | #Place Bid Order: 203 | bid_order1 = client.order_limit_buy( 204 | symbol=coin, 205 | quantity=quant1, 206 | price=place_bid_order) 207 | #Place Ask Order 208 | ask_order1 = client.order_limit_sell( 209 | symbol=coin, 210 | quantity=quant1, 211 | price=place_ask_order) 212 | 213 | 214 | #Place second order if current spread > 0.05% (transaction fee) 215 | 216 | """ 217 | 218 | 219 | def visualize_market_depth(wait_time_sec='1', tot_time='1', sym='ICXBNB', precision=5): 220 | cycles = int(tot_time)/int(wait_time_sec) 221 | start_time = time.asctime() 222 | fig, ax = plt.subplots() 223 | for i in range(1,int(cycles)+1): 224 | ask_pri, ask_quan, bid_pri, bid_quan, ask_order, bid_order = market_depth(sym) 225 | 226 | #print(ask_price) 227 | plt.plot(ask_pri, ask_quan, color = 'red', label='asks-cycle: {}'.format(i)) 228 | plt.plot(bid_pri, bid_quan, color = 'blue', label = 'bids-cycle: {}'.format(i)) 229 | 230 | #ax.plot(depth['bids'][0], depth['bids'][1]) 231 | max_bid = max(bid_pri) 232 | min_ask = min(ask_pri) 233 | max_quant = max(ask_quan[-1], bid_quan[-1]) 234 | spread = round(((min_ask-max_bid)/min_ask)*100,5) #Spread based on market 235 | proj_order_spread = round(((ask_order-bid_order)/ask_order)*100, precision) 236 | price=round(((max_bid+min_ask)/2), precision) 237 | plt.plot([price, price],[0, max_quant], color = 'green', label = 'Price - Cycle: {}'.format(i)) #Vertical Line for Price 238 | plt.plot([ask_order, ask_order],[0, max_quant], color = 'black', label = 'Ask - Cycle: {}'.format(i)) 239 | plt.plot([bid_order, bid_order],[0, max_quant], color = 'black', label = 'Buy - Cycle: {}'.format(i)) 240 | #plt.plot([min_ask, min_ask],[0, max_quant], color = 'grey', label = 'Min Ask - Cycle: {}'.format(i)) 241 | #plt.plot([max_bid, max_bid],[0, max_quant], color = 'grey', label = 'Max Buy - Cycle: {}'.format(i)) 242 | ax.annotate("Max Bid: {} \nMin Ask: {}\nSpread: {} %\nCycle: {}\nPrice: {}" 243 | "\nPlace Bid: {} \nPlace Ask: {}\n Projected Spread: {} %".format(max_bid, min_ask, spread, i, price, bid_order, ask_order, proj_order_spread), 244 | xy=(max_bid, ask_quan[-1]), xytext=(max_bid, ask_quan[0])) 245 | if i==(cycles+1): 246 | break 247 | else: 248 | time.sleep(int(wait_time_sec)) 249 | #end_time = time.asctime() 250 | ax.set(xlabel='Price', ylabel='Quantity', 251 | title='Binance Order Book: {} \n {}\n Cycle Time: {} seconds - Num Cycles: {}'.format(sym, start_time, wait_time_sec, cycles)) 252 | plt.legend() 253 | plt.show() 254 | return ask_pri, ask_quan, bid_pri, bid_quan, ask_order, bid_order, spread, proj_order_spread, max_bid, min_ask 255 | 256 | 257 | def coin_prices(watch_list): 258 | #Will print to screen, prices of coins on 'watch list' 259 | #returns all prices 260 | prices = client.get_all_tickers() 261 | print("\nSelected (watch list) Ticker Prices: ") 262 | for price in prices: 263 | if price['symbol'] in watch_list: 264 | print(price) 265 | return prices 266 | 267 | 268 | def coin_tickers(watch_list): 269 | # Prints to screen tickers for 'watch list' coins 270 | # Returns list of all price tickers 271 | tickers = client.get_orderbook_tickers() 272 | print("\nWatch List Order Tickers: \n") 273 | for tick in tickers: 274 | if tick['symbol'] in watch_list: 275 | print(tick) 276 | return tickers 277 | 278 | def portfolio_management(deposit = '10000', withdraw=0, portfolio_amt = '0', portfolio_type='USDT', test_acct='True'): 279 | """The Portfolio Management Function will be used to track profit/loss of Portfolio in Any Particular Currency (Default: USDT)""" 280 | #Maintain Portfolio Statistics (Total Profit/Loss) in a file 281 | pass 282 | 283 | def Bollinger_Bands(): 284 | #This Function will calculate Bollinger Bands for Given Time Period 285 | #EDIT: Will use Crypto-Signal for this functionality 286 | #https://github.com/CryptoSignal/crypto-signal 287 | pass 288 | 289 | def buy_sell_bot(): 290 | pass 291 | 292 | def position_sizing(): 293 | pass 294 | 295 | def trailing_stop_loss(): 296 | pass 297 | 298 | 299 | #Place Limit Order 300 | """ 301 | order = client.order_limit_buy( 302 | symbol='BNBBTC', 303 | quantity=100, 304 | price='0.00001') 305 | 306 | order = client.order_limit_sell( 307 | symbol='BNBBTC', 308 | quantity=100, 309 | price='0.00001') 310 | """ 311 | 312 | 313 | 314 | 315 | """ 316 | #trade aggregator (generator) 317 | agg_trades = client.aggregate_trade_iter(symbol='ETHBTC', start_str='30 minutes ago UTC') 318 | # iterate over the trade iterator 319 | for trade in agg_trades: 320 | pass 321 | #print(trade) 322 | # do something with the trade data 323 | 324 | # convert the iterator to a list 325 | # note: generators can only be iterated over once so we need to call it again 326 | agg_trades = client.aggregate_trade_iter(symbol='ETHBTC', start_str='30 minutes ago UTC') 327 | agg_trade_list = list(agg_trades) 328 | 329 | # fetch 30 minute klines for the last month of 2017 330 | klines = client.get_historical_klines("ETHBTC", Client.KLINE_INTERVAL_30MINUTE, "1 Dec, 2017", "1 Jan, 2018") 331 | #for kline in klines: 332 | #print(kline) 333 | """ 334 | 335 | #place an order on Binance 336 | """ 337 | order = client.create_order( 338 | symbol='BNBBTC', 339 | side=SIDE_BUY, 340 | type=ORDER_TYPE_LIMIT, 341 | timeInForce=TIME_IN_FORCE_GTC, 342 | quantity=100, 343 | price='0.00001') 344 | """ 345 | 346 | if __name__ == "__main__": 347 | run() 348 | -------------------------------------------------------------------------------- /Crypto-Trading-Bots/Crypto_Sentiment_Analysis_SocialMedia_Bot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Twitter Sentiment Analysis in Python - A bot which will monitor, store and categorize Sentiment Analysis based on Twitter 3 | for cryptocurrencies, and implement a strategy for profitable trading based on Bitcoin Barbie Bot (BBB) Strategy, described here: 4 | 5 | https://medium.com/@BlockchainEng/crypto-trading-bot-sentiment-analysis-bot-bfbd8dd1df5a 6 | 7 | Youtube Series Here: 8 | 6/30/2018 9 | source of BitcoinPrice() code: https://gist.github.com/mattvukas/9146611 10 | 11 | @BlockchainEng 12 | Copyright 2018 - All Rights Reserved 13 | """ 14 | 15 | def run(): 16 | #This Bot is to perform sentiment analysis, then implement a trade strategy based on sentiment and price 17 | """ 18 | Monitor, collect and save tweets mentioning Cryptocurrency Y in file format. 19 | Perform Sentiment Analysis on a historic data set, and recent tweets during a specified time period (1 hour, 5 minutes, 1 day). Track and record historical values in file format. Visualize data through python script. 20 | Trade structure attempting to mimic this strategy: 21 | If Sentiment positive (‘buy’) and green candle (‘higher price’), wait to purchase coins. 22 | If candle decreases 2% (or more) in specified time period (5 minutes, 1 hour, 1 day), Purchase quantity of coin. 23 | Sell when price increases 5% (adjustable). 24 | To Reiterate, the functionality of of a bot to implement this strategy is based on a python script that will: 25 | 26 | Monitor all tweets mentioning X-Coin, perform sentiment analysis to determine buy/sell signalling from crypto-accounts 27 | Track Historical Values in CSV spreadsheet format 28 | Compare current/recent values to historic values 29 | Tweet out ‘Alerts’ based on strategy, and perform successful trades on Binance 30 | 31 | :return: 32 | """ 33 | #Instructions: https://www.geeksforgeeks.org/twitter-sentiment-analysis-using-python/ 34 | import tweepy 35 | import textblob 36 | import time 37 | #textblob.download_corpora() 38 | from datetime import datetime 39 | import re 40 | import tweepy 41 | from tweepy import OAuthHandler 42 | from textblob import TextBlob 43 | import matplotlib.pyplot as plt 44 | import requests, json 45 | from time import sleep 46 | 47 | class TwitterClient(object): 48 | ''' 49 | Generic Twitter Class for sentiment analysis. 50 | ''' 51 | def __init__(self): 52 | ''' 53 | Class constructor or initialization method. 54 | ''' 55 | # keys and tokens from the Twitter Dev Console 56 | consumer_key = '' 57 | consumer_secret = '' 58 | access_token = '' 59 | access_token_secret = '' 60 | 61 | # attempt authentication 62 | try: 63 | # create OAuthHandler object 64 | self.auth = OAuthHandler(consumer_key, consumer_secret) 65 | # set access token and secret 66 | self.auth.set_access_token(access_token, access_token_secret) 67 | # create tweepy API object to fetch tweets 68 | self.api = tweepy.API(self.auth) 69 | except: 70 | print("Error: Authentication Failed") 71 | 72 | def clean_tweet(self, tweet): 73 | ''' 74 | Utility function to clean tweet text by removing links, special characters 75 | using simple regex statements. 76 | ''' 77 | return ' '.join(re.sub("(@[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)", " ", tweet).split()) 78 | 79 | def get_tweet_sentiment(self, tweet): 80 | ''' 81 | Utility function to classify sentiment of passed tweet 82 | using textblob's sentiment method 83 | ''' 84 | # create TextBlob object of passed tweet text 85 | analysis = TextBlob(self.clean_tweet(tweet)) 86 | # set sentiment 87 | if analysis.sentiment.polarity > 0: 88 | return 'positive' 89 | elif analysis.sentiment.polarity == 0: 90 | return 'neutral' 91 | else: 92 | return 'negative' 93 | 94 | def tweet_file(self): 95 | self.message="Sentiment Analysis by @BlockchainEng" 96 | self.filename='SentimentAnalysis.png' 97 | print(self) 98 | self.api.update_with_media(message = self.message, filename= self.filename) 99 | 100 | def get_tweets(self, query, count = 10): 101 | ''' 102 | Main function to fetch tweets and parse them. 103 | ''' 104 | # empty list to store parsed tweets 105 | tweets = [] 106 | 107 | try: 108 | # call twitter api to fetch tweets 109 | fetched_tweets = self.api.search(q = query, count = count) 110 | 111 | # parsing tweets one by one 112 | list_of_tweets = [] 113 | for tweet in fetched_tweets: 114 | 115 | # empty dictionary to store required params of a tweet 116 | parsed_tweet = {} 117 | 118 | # saving text of tweet 119 | #tweet1 = 120 | #tweet1=TwitterClient.api.clean_tweet(tweet_text) 121 | parsed_tweet['text'] = tweet.text 122 | list_of_tweets.append(tweet.text) 123 | # saving sentiment of tweet 124 | parsed_tweet['sentiment'] = self.get_tweet_sentiment(tweet.text) 125 | 126 | # appending parsed tweet to tweets list 127 | if tweet.retweet_count > 0: 128 | # if tweet has retweets, ensure that it is appended only once 129 | if parsed_tweet not in tweets: 130 | tweets.append(parsed_tweet) 131 | else: 132 | tweets.append(parsed_tweet) 133 | 134 | # return parsed tweets 135 | with open('TweetHistory.txt', 'a+') as f1: 136 | for tweet in list_of_tweets: 137 | try: 138 | f1.write(tweet) 139 | except: 140 | pass 141 | 142 | return tweets 143 | 144 | except tweepy.TweepError as e: 145 | # print error (if any) 146 | print("Error : " + str(e)) 147 | 148 | def main(): 149 | # creating object of TwitterClient Class 150 | api = TwitterClient() 151 | # calling function to get tweets 152 | search_term = 'Bitcoin' 153 | list_coins=['Bitcoin'] #, 'Ethereum', 'EOS', 'Cryptocurrency', 'Blockchain', 'BTC'] #'Donald Trump', 'Barack Obama', 'George Washington'] 154 | count1=200 155 | list_coin_val = [] 156 | start_time = datetime.now() 157 | try: 158 | for i in range(0,60): 159 | #This For Loop controls how many data 'cycles' are collected before visualization and tweeting 160 | for coin in list_coins: 161 | tweets = api.get_tweets(query = coin, count = count1) 162 | 163 | # picking positive tweets from tweets 164 | ptweets = [tweet for tweet in tweets if tweet['sentiment'] == 'positive'] 165 | # percentage of positive tweets 166 | print("\n\nTime: {}".format(str(datetime.now()))) 167 | print("Sentiment Values for {}\nNumber of Tweets Analyzed: {}".format(coin, count1)) 168 | positive_tweet_percentage = round(100*len(ptweets)/len(tweets),6) 169 | print("Positive tweets percentage: {} %".format(positive_tweet_percentage)) 170 | # picking negative tweets from tweets 171 | ntweets = [tweet for tweet in tweets if tweet['sentiment'] == 'negative'] 172 | # percentage of negative tweets 173 | negative_tweet_percentage = round(100*len(ntweets)/len(tweets),6) 174 | print("Negative tweets percentage: {} %".format(negative_tweet_percentage)) 175 | # percentage of neutral tweets 176 | neutral_tweet_percentage = round(100*(len(tweets) - len(ntweets) - len(ptweets))/len(tweets),6) 177 | print("Neutral tweets percentage: {} % \ 178 | ".format(neutral_tweet_percentage)) 179 | current_price = getBitcoinPrice() 180 | list_coin_val.append([coin, positive_tweet_percentage, negative_tweet_percentage, neutral_tweet_percentage, str(datetime.now()), current_price]) 181 | save_to_file(coin, positive_tweet_percentage, negative_tweet_percentage, neutral_tweet_percentage, datetime.now(), current_price, "SentimentHistorical.csv") 182 | print("Current Price: {}".format(getBitcoinPrice())) 183 | trading(current_price, positive_tweet_percentage, negative_tweet_percentage) #used for Trading Signals 184 | time.sleep(30) 185 | end_time = datetime.now() 186 | print(list_coin_val, start_time, end_time) 187 | except: 188 | print("ERROR - COLLECTING DATA") 189 | try: 190 | #msg = 'Sentiment Analysis - Twitter \nvia @BlockchainEngineer \n\n #cryptocurrency #bitcoin #bitcointrading' 191 | #filename = 'SentimentAnalysis.png' 192 | #api.tweet_file() 193 | data_visualize(api, list_coin_val, start_time, end_time) 194 | #historic_data_viz(api) 195 | except: 196 | print("ERROR - COLLECTING DATA") 197 | 198 | def save_to_file(coin, positive_tweet_percentage, negative_tweet_percentage, neutral_tweet_percentage, time, current_price, filename = "SentimentHistorical.csv"): 199 | with open(filename, 'a+') as f: 200 | line = coin, positive_tweet_percentage, negative_tweet_percentage, neutral_tweet_percentage, time, current_price 201 | f.writelines(str(line) + '\n') 202 | def getBitcoinPrice(): 203 | URL = 'https://www.bitstamp.net/api/ticker/' 204 | try: 205 | r = requests.get(URL) 206 | priceFloat = float(json.loads(r.text)['last']) 207 | return priceFloat 208 | except requests.ConnectionError: 209 | print("Error querying Bitstamp API") 210 | 211 | def tweet_file(self, message, filename): 212 | #message = "Sentiment Analysis by @BlockchainEng" 213 | #filename ='SentimentAnalysis.png' 214 | self.api.update_with_media(message, filename) 215 | 216 | def historic_data_viz(self): 217 | #Load Historic Data and Visual into graph form for entire recorded amount 218 | historic_data_list = [] 219 | i=0 220 | with open('SentimentHistorical.csv') as f1: 221 | lines = list(f1.readlines()) 222 | for line in lines: 223 | print(line) 224 | data=list(line.split(',')) 225 | print(data) 226 | if i==0: 227 | start_time=data[5] 228 | if i==len(f1.readlines()): 229 | end_time=data[5] 230 | historic_data_list.append(data) 231 | i+=1 232 | data_visualize(historic_data_list, start_time, end_time, self) 233 | 234 | def trading(current_price, positive_sentiment_percent, negative_sentiment_percent): 235 | print("Positive Sentiment - Negative Sentiment (Net Positive)", positive_sentiment_percent-negative_sentiment_percent) 236 | if positive_sentiment_percent>0.3: 237 | #Buy 238 | #use Khal's Code to place order, entries & exits 239 | print("TEST - BUY SIGNAL") 240 | pass 241 | if negative_sentiment_percent>0.2: 242 | #Sell 243 | print("TEST - SELL SIGNAL") 244 | #use Khal's Code to place order, entries & exits 245 | pass 246 | 247 | def data_visualize(api, list_coins, start_time, end_time): 248 | visualize_price = [] 249 | name_list = [] 250 | positive_tweet = [] 251 | negative_tweet = [] 252 | neutral_tweet = [] 253 | time_list = [] 254 | for coin in list_coins: 255 | print("COIN: ", coin) 256 | print(positive_tweet) 257 | print(coin[0]) 258 | name_list.append(coin[0]) 259 | positive_tweet.append(coin[1]) 260 | print(coin[1]) 261 | negative_tweet.append(coin[2]) 262 | neutral_tweet.append(coin[3]) 263 | time_list.append(coin[4]) 264 | visualize_price.append(coin[5]) 265 | #Converted to two axis on same graph - https://matplotlib.org/gallery/api/two_scales.html 266 | fig, ax1 = plt.subplots() 267 | 268 | color = 'black' 269 | ax1.set_xlabel('time') 270 | ax1.set_ylabel('Percentage', color=color) 271 | plt.title("Sentiment Analysis through Twitter \nCopyright 2018 (c) by @BlockchainEng") 272 | #ax1.plot(t, data1, color=color) 273 | ax1.plot(time_list, positive_tweet, 'g', label='Positive %') 274 | ax1.plot(time_list, negative_tweet, 'r', label='Negative %') 275 | ax1.plot(time_list, neutral_tweet, 'k', label = 'Neutral %') 276 | ax1.tick_params(axis='y', labelcolor=color) 277 | plt.legend() 278 | ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis 279 | 280 | color = 'blue' 281 | ax2.set_ylabel('Price ($)', color=color) # we already handled the x-label with ax1 282 | #ax2.plot(t, data2, color=color) 283 | ax2.plot(time_list, visualize_price, 'b', label='Bitcoin Price (Bitstamp)') 284 | ax2.tick_params(axis='y', labelcolor=color) 285 | plt.legend() 286 | fig.tight_layout() # otherwise the right y-label is slightly clipped 287 | """ 288 | #print(positive_tweet) 289 | fig = plt.figure(1) 290 | plt.subplot(211) 291 | plt.plot(time_list, positive_tweet, 'g', label='Positive Tweet Percentage') 292 | plt.plot(time_list, negative_tweet, 'r', label='Negative Tweet Percentage') 293 | plt.plot(time_list, neutral_tweet, 'k', label = 'Neutral Tweet Percentage') 294 | plt.legend() 295 | plt.subplot(212) 296 | plt.plot(time_list, visualize_price, 'b', label='Bitcoin Price (Bitstamp)') 297 | plt.suptitle('{} Sentiment Analysis, 200 Tweets (each)\n{} - {} '.format(name_list[0], start_time, end_time)) 298 | plt.legend() 299 | plt.ylabel('Percentage') 300 | plt.xlabel('Time') 301 | #plt.show() 302 | """ 303 | plt.legend() 304 | #ax2.title('{} Sentiment Analysis, 200 Tweets (each)\n{} - {} '.format(name_list[0], start_time, end_time)) 305 | filename='SentimentAnalysis.png' #+str(start_time).strip()+'.png' 306 | fig.savefig(filename) 307 | #tweet out fig and message 308 | msg = "@Twitter Sentiment Analysis for conversation around #Bitcoin - 200 tweets measured each cycle" 309 | msg+= "\n\n Includes price. \n\nvia @BlockchainEng \n\n #SentimentAnalysis #BitcoinTrading #Bitcoin" 310 | api.tweet_file() 311 | """ 312 | # printing first 5 positive tweets 313 | print("\n\nPositive tweets:") 314 | for tweet in ptweets[:10]: 315 | print(tweet['text']) 316 | 317 | # printing first 5 negative tweets 318 | print("\n\nNegative tweets:") 319 | for tweet in ntweets[:10]: 320 | print(tweet['text']) 321 | """ 322 | 323 | if __name__ == "__main__": 324 | # calling main function 325 | while 1: 326 | main() 327 | -------------------------------------------------------------------------------- /Historic-Legacy/CryptoTriangularArbitrageBinanceBot.py: -------------------------------------------------------------------------------- 1 | """ 2 | The Purpose of the Binance Arbitrage Bot (based on RoibalBot) Python Program is to create an automated trading bot (functionality) on Binance 3 | Utilized Python-Binance ( https://github.com/sammchardy/python-binance ) 4 | Advanced-Version capable of all exchanges, all coins (using cctx) 5 | 6 | Created 4/14/2018 by Joaquin Roibal 7 | V 0.01 - Updated 4/20/2018 8 | v 0.02 - Updated 5/30/2018 - Converted to Advanced Version: https://github.com/Roibal/Cryptocurrency-Trading-Bots-Python-Beginner-Advance 9 | v 0.03 - Created 6/18/2018 - Binance Arbitrage Bot 10 | v 0.04 - 6/21/2018 - Changed Name to CryptoTriangularArbitrageBinanceBot.py 11 | Licensed under MIT License 12 | 13 | Instructional Youtube Video: https://www.youtube.com/watch?v=8AAN03M8QhA 14 | 15 | Did you enjoy the functionality of this bot? Tips always appreciated. 16 | 17 | BTC: 1BYrAED4pi5DMKu2qZPv8pwe6rEeuxoCiD 18 | ETH: 19 | 20 | NOTE: All Subsequent Version of Program must contain this message, unmodified, in it's entirety 21 | Copyright (c) 2018 by Joaquin Roibal 22 | """ 23 | 24 | from binance.client import Client 25 | import time 26 | from datetime import datetime 27 | import matplotlib 28 | from matplotlib import cm 29 | import matplotlib.pyplot as plt 30 | from binance.enums import * 31 | #import save_historical_data_Roibal 32 | from BinanceKeys import BinanceKey1 33 | 34 | api_key = BinanceKey1['api_key'] 35 | api_secret = BinanceKey1['api_secret'] 36 | 37 | client = Client(api_key, api_secret) 38 | 39 | def run(): 40 | #Initialize Arbitrage Binance Bot 41 | initialize_arb() 42 | #Get Binance Wallet Balance - Split into 4 coins evenly 43 | 44 | #Perform our Arbitrage Function 45 | 46 | #Data Output (log) in a text file - keep track of start/end time, trades, balance 47 | pass 48 | 49 | def initialize_arb(): 50 | 51 | welcome_message = "\n\n---------------------------------------------------------\n\n" 52 | welcome_message+= "Hello and Welcome to the Binance Arbitrage Crypto Trader Bot Python Script\nCreated 2018 by Joaquin Roibal (@BlockchainEng)" 53 | welcome_message+= "A quick 'run-through' will be performed to introduce you to the functionality of this bot\n" 54 | welcome_message+="To learn more visit medium.com/@BlockchainEng or watch introductory Youtube Videos" 55 | welcome_message+="\nCopyright 2018 by Joaquin Roibal\n" 56 | bot_start_time = str(datetime.now()) 57 | welcome_message+= "\nBot Start Time: {}\n\n\n".format(bot_start_time) 58 | print(welcome_message) 59 | #output to file - create function 60 | data_log_to_file(welcome_message) 61 | time.sleep(5) 62 | try: 63 | status = client.get_system_status() 64 | #print("\nExchange Status: ", status) 65 | 66 | #Account Withdrawal History Info 67 | withdraws = client.get_withdraw_history() 68 | #print("\nClient Withdraw History: ", withdraws) 69 | 70 | #for symbol in list_of_symbols: 71 | #market_depth(symbol) 72 | #Collect all Symbols for Exchange 73 | #Find Arbitrage Opportunities 74 | list_of_symbols = ['ETHBTC', 'BNBETH', 'BNBBTC'] 75 | list_of_symbols2 = ['ETHUSDT', 'BNBETH', 'BNBUSDT'] 76 | list_of_symbols3 = ['BTCUSDT', 'BNBBTC', 'BNBUSDT'] 77 | list_of_arb_sym = [list_of_symbols, list_of_symbols2, list_of_symbols3] 78 | #for sym in list_of_symbols: 79 | #info = client.get_symbol_info(sym) 80 | #print(info) 81 | #prices = client.get_all_tickers() 82 | tickers = client.get_orderbook_tickers() 83 | #print(prices) 84 | #print(tickers) 85 | #portfolio = [10, 100, 10000, 500, str(datetime.now())] #Number of: [Bitcoin, Ethereum, USDT, Binance Coin] 86 | #Load Portfolio File 87 | portfolio=[] 88 | with open('Portfolio.txt') as f1: 89 | read_data = f1.readlines() 90 | for line in read_data: 91 | load_portfolio = line #Load Previous Portfolio 92 | load_portfolio = list(load_portfolio[1:-1].split(',')) 93 | #print(load_portfolio) 94 | #time.sleep(5) 95 | #for i in range(0,3): 96 | #portfolio[i] = float(portfolio[i]) #Set Type for first 4 values of Portfolio 97 | i=0 98 | for val in load_portfolio: 99 | #print(val.strip()) 100 | if i == 4: 101 | portfolio.append(str(datetime.now())) 102 | break 103 | portfolio.append(float(val)) 104 | i+=1 105 | portf_msg = "Starting Portfolio: " + str(portfolio) 106 | print(portf_msg) 107 | portf_file_save(portfolio) 108 | data_log_to_file(portf_msg) 109 | while 1: 110 | #Run Arbitrage Profit Functionality - To Determine Highest Profit Percentage - Cont Loop 111 | calc_profit_list =[] 112 | for arb_market in list_of_arb_sym: 113 | calc_profit_list.append(arbitrage_bin(arb_market, tickers, portfolio, 1, 1)) 114 | 115 | for profit1 in calc_profit_list: 116 | data_log_to_file(str(profit1)) 117 | print(calc_profit_list) 118 | exp_profit = 0 #Expected Profit, Set to 0 initially 119 | m = n = 0 #Market Position Market 120 | for exch_market in calc_profit_list: 121 | if exch_market[4]>exp_profit: 122 | exp_profit = exch_market[4] 123 | m = n 124 | n+=1 125 | profit_message = "\nMost Profitable Market: {} \nExpected Profit: {}%".format(list_of_arb_sym[m], exp_profit) 126 | print(profit_message) 127 | data_log_to_file(profit_message) 128 | time.sleep(5) 129 | #Run Arbitrage Function on Highest Profit Percentage Coin for 10 minutes 130 | arb_list_data = [] 131 | arb_start_time = str(datetime.now()) 132 | for i in range(0,5): 133 | #Collect Arbitrage Data Into List format for 5 cycles, 30 second cycles (replaces functionality) 134 | arb_list_data.append(arbitrage_bin(list_of_arb_sym[m], tickers, portfolio, 1, 1, 'Yes')) #'Yes' to place orders 135 | #print(arb_list_data) 136 | time.sleep(30) 137 | arb_end_time = str(datetime.now()) 138 | #Visualize Collected Arb List Data with MatPlotLib 139 | viz_arb_data(arb_list_data, list_of_arb_sym[m], arb_start_time, arb_end_time) 140 | except: 141 | print("\nFAILURE INITIALIZE\n") 142 | 143 | def data_log_to_file(message): 144 | with open('CryptoTriArbBot_DataLog.txt', 'a+') as f: 145 | f.write(message) 146 | 147 | def portf_file_save(portfolio): 148 | with open('Portfolio.txt', 'a+') as f: 149 | f.write('\n'+str(portfolio)) 150 | 151 | def arbitrage_bin(list_of_sym, tickers, portfolio, cycle_num=10, cycle_time=30, place_order='No'): 152 | #Create Triangular Arbitrage Function 153 | arb_message = "Beginning Binance Arbitrage Function Data Collection - Running\n" 154 | print(arb_message) 155 | data_log_to_file(arb_message) 156 | time.sleep(2) 157 | fee_percentage = 0.05 #divided by 100 158 | #Created Arbitrage Functionality for with Python-Binance 159 | for i in range(0,1): #initialize Exchange 160 | #create blacklist of exchanges 161 | 162 | #exchange1 = getattr (ccxt, exch) () 163 | #symbols = tickers.keys() 164 | #print(symbols) 165 | #time.sleep(20) 166 | #Find Pairs to Trade 167 | """ 168 | pairs = [] 169 | for sym in symbols: 170 | for symbol in coins: 171 | if symbol in sym: 172 | pairs.append(sym) 173 | print(pairs) 174 | #From Coin 1 to Coin 2 - ETH/BTC - Bid 175 | #From Coin 2 to Coin 3 - ETH/LTC - Ask 176 | #From Coin 3 to Coin 1 - BTC/LTC - Bid 177 | arb_list = ['ETH/BTC'] #, 'ETH/LTC', 'BTC/LTC'] 178 | #Find 'closed loop' of currency rate pairs 179 | j=0 180 | while 1: 181 | if j == 1: 182 | final = arb_list[0][-3:] + '/' + str(arb_list[1][-3:]) 183 | print(final) 184 | #if final in symbols: 185 | arb_list.append(final) 186 | break 187 | for sym in symbols: 188 | if sym in arb_list: 189 | pass 190 | else: 191 | if j % 2 == 0: 192 | if arb_list[j][0:3] == sym[0:3]: 193 | if arb_list[j] == sym: 194 | pass 195 | else: 196 | arb_list.append(sym) 197 | print(arb_list) 198 | j+=1 199 | break 200 | if j % 2 == 1: 201 | if arb_list[j][-3:] == sym[-3:]: 202 | if arb_list[j] == sym: 203 | pass 204 | else: 205 | arb_list.append(sym) 206 | print(arb_list) 207 | j+=1 208 | break 209 | """ 210 | #time.sleep(.5) 211 | print("List of Arbitrage Symbols:", list_of_sym) 212 | #time.sleep(3) 213 | #Determine Rates for our 3 currency pairs - order book 214 | list_exch_rate_list = [] 215 | if 1: 216 | #Create Visualization of Currency Exchange Rate Value - Over Time 217 | #Determine Cycle number (when data is taken) and time when taken 218 | for k in range(0,cycle_num): 219 | i=0 220 | exch_rate_list = [] 221 | data_collect_message1 = "Data Collection Cycle Number: "+str(k) +'\n' 222 | print(data_collect_message1) 223 | data_log_to_file(data_collect_message1) 224 | for sym in list_of_sym: 225 | currency_pair = "Currency Pair: "+str(sym)+"\n" 226 | print(currency_pair) 227 | data_log_to_file(currency_pair) 228 | if sym in list_of_sym: 229 | #depth = client.get_(sym) 230 | #print(depth) 231 | """if i == 0: #For first in triangle 232 | depth = client.get_order_book(symbol=sym) 233 | exch_rate_list.append(float(depth['bids'][0][0])) 234 | print(depth['bids'][0][0]) 235 | """ 236 | if i % 2==0: 237 | #exch_rate_list.append(depth['bids'][0][0]) #converted to Binance 238 | depth = client.get_order_book(symbol=sym) 239 | inv1 = depth['asks'][0][0] 240 | exch_rate_list.append(float(inv1)) #Inverse Because of Binance Format 241 | Exch_rate1 = "Exchange Rate: {}".format(depth['asks'][0][0]) +'\n' 242 | print(Exch_rate1) 243 | data_log_to_file(Exch_rate1) 244 | if i == 1: 245 | #exch_rate_list.append(depth['asks'][0][0]) 246 | depth = client.get_order_book(symbol=sym) 247 | inv2 = round(1.0/float(depth['bids'][0][0]),6) 248 | exch_rate_list.append(float(inv2)) #Inverse because Binance Format 249 | Exch_rate2 = "Exchange Rate: {}".format(depth['bids'][0][0])+'\n' 250 | print(Exch_rate2) 251 | data_log_to_file(Exch_rate2) 252 | i+=1 253 | else: 254 | exch_rate_list.append(0) 255 | 256 | #exch_rate_list.append(((rateB[-1]-rateA[-1])/rateA[-1])*100) #Expected Profit 257 | exch_rate_list.append(datetime.now()) #changed to Human Readable time 258 | #time.sleep(10) 259 | #Compare to determine if Arbitrage opp exists 260 | rate1 = exch_rate_list[0] 261 | buy_price = "Buy: {}\n".format(rate1) 262 | print(buy_price) 263 | data_log_to_file(buy_price) 264 | rate2 = float(exch_rate_list[2])*float(exch_rate_list[1]) 265 | sell_price = "Sell: {}\n".format(rate2) 266 | print(sell_price) 267 | data_log_to_file(sell_price) 268 | if float(rate1)float(max_order_ask): 440 | #Determine Price to place ask order based on highest volume 441 | max_order_ask=ask[1] 442 | place_order_ask_price=round(float(ask[0]),5)-0.0001 443 | #ask_list.append([ask[0], ask[1]]) 444 | ask_price.append(float(ask[0])) 445 | ask_tot+=float(ask[1]) 446 | ask_quantity.append(ask_tot) 447 | #print(ask) 448 | i+=1 449 | j=0 #Secondary Counter for Bids 450 | print("\n", sym, "\nDepth BIDS:\n") 451 | print("Price Amount") 452 | for bid in depth['bids']: 453 | if jfloat(max_order_bid): 455 | #Determine Price to place ask order based on highest volume 456 | max_order_bid=bid[1] 457 | place_order_bid_price=round(float(bid[0]),5)+0.0001 458 | bid_price.append(float(bid[0])) 459 | bid_tot += float(bid[1]) 460 | bid_quantity.append(bid_tot) 461 | #print(bid) 462 | j+=1 463 | return ask_price, ask_quantity, bid_price, bid_quantity, place_order_ask_price, place_order_bid_price 464 | #Plot Data 465 | """ 466 | if __name__ == "__main__": 467 | run() 468 | -------------------------------------------------------------------------------- /Crypto-Trading-Bots/Advanced_Cryptocurrency_Trading_Bot.py: -------------------------------------------------------------------------------- 1 | """ 2 | The Purpose of the RoibalBot Python Program is to create an automated trading bot (functionality) on Binance 3 | Beginner Version Utilized Python-Binance ( https://github.com/sammchardy/python-binance ) 4 | Advanced-Version capable of all exchanges, all coins (using ccxt) 5 | 6 | Created 4/14/2018 by Joaquin Roibal 7 | V 0.01 - Updated 4/20/2018 8 | v 0.02 - Updated 5/30/2018 - Converted to Advanced Version: https://github.com/Roibal/Cryptocurrency-Trading-Bots-Python-Beginner-Advance 9 | 10 | Licensed under MIT License 11 | 12 | Introduction Youtube Video: https://www.youtube.com/watch?v=8AAN03M8QhA 13 | Advanced Cryptocurrency Trading Bot: https://www.youtube.com/watch?v=HzibFcWNd-s 14 | 15 | Did you enjoy the functionality of this bot? Tips always appreciated. 16 | 17 | BTC: 18 | ETH: 19 | 20 | NOTE: All Subsequent Version of Program must contain this message, unmodified, in it's entirety 21 | Copyright (c) 2018 by Joaquin Roibal 22 | """ 23 | 24 | #import save_historical_data_Roibal 25 | #from binance.client import Client 26 | #from binance.enums import * 27 | import ccxt 28 | import time 29 | import matplotlib.pyplot as plt 30 | import random 31 | from pprint import pprint 32 | #from Keys import Key1 33 | 34 | #api_key = BinanceKey1['api_key'] 35 | #api_secret = BinanceKey1['api_secret'] 36 | #client = Client(api_key, api_secret) 37 | 38 | #Get a deposit address for BTC 39 | #address = client.get_deposit_address(asset='BTC') 40 | 41 | def run(): 42 | #Initialize Function - Set Initial Conditions for Bot 43 | arbitrage() 44 | time.sleep(20) 45 | initialize() 46 | #Diversify Funtion - Collect all balances across exchange, then diversify them 47 | #diversify() 48 | portfolio = 10 #BTC 49 | #Active Trader - 'scalping', swing trading, arbitrage 50 | while 1: 51 | ActiveTrader() 52 | 53 | def arbitrage(cycle_num=5, cycle_time=240): 54 | #Create Triangular Arbitrage Function 55 | print("Arbitrage Function Running") 56 | fee_percentage = 0.001 #divided by 100 57 | coins = ['BTC', 'LTC', 'ETH'] #Coins to Arbitrage 58 | #Create Functionality for Binance 59 | for exch in ccxt.exchanges: #initialize Exchange 60 | exchange1 = getattr (ccxt, exch) () 61 | symbols = exchange1.symbols 62 | if symbols is None: 63 | print("Skipping Exchange ", exch) 64 | print("\n-----------------\nNext Exchange\n-----------------") 65 | elif len(symbols)<15: 66 | print("\n-----------------\nNeed more Pairs (Next Exchange)\n-----------------") 67 | else: 68 | print(exchange1) 69 | 70 | exchange1_info = dir(exchange1) 71 | print("------------Exchange: ", exchange1.id) 72 | #pprint(exchange1_info) 73 | print(exchange1.symbols) #List all currencies 74 | time.sleep(5) 75 | #Find Currencies Trading Pairs to Trade 76 | pairs = [] 77 | for sym in symbols: 78 | for symbol in coins: 79 | if symbol in sym: 80 | pairs.append(sym) 81 | print(pairs) 82 | #From Coin 1 to Coin 2 - ETH/BTC - Bid 83 | #From Coin 2 to Coin 3 - ETH/LTC - Ask 84 | #From Coin 3 to Coin 1 - BTC/LTC - Bid 85 | arb_list = ['ETH/BTC'] #, 'ETH/LTC', 'BTC/LTC'] 86 | #Find 'closed loop' of currency rate pairs 87 | j=0 88 | while 1: 89 | if j == 1: 90 | final = arb_list[0][-3:] + '/' + str(arb_list[1][-3:]) 91 | print(final) 92 | #if final in symbols: 93 | arb_list.append(final) 94 | break 95 | for sym in symbols: 96 | if sym in arb_list: 97 | pass 98 | else: 99 | if j % 2 == 0: 100 | if arb_list[j][0:3] == sym[0:3]: 101 | if arb_list[j] == sym: 102 | pass 103 | else: 104 | arb_list.append(sym) 105 | print(arb_list) 106 | j+=1 107 | break 108 | if j % 2 == 1: 109 | if arb_list[j][-3:] == sym[-3:]: 110 | if arb_list[j] == sym: 111 | pass 112 | else: 113 | arb_list.append(sym) 114 | print(arb_list) 115 | j+=1 116 | break 117 | 118 | #time.sleep(.5) 119 | print("List of Arbitrage Symbols:", arb_list) 120 | #time.sleep(3) 121 | #Determine Rates for our 3 currency pairs - order book 122 | list_exch_rate_list = [] 123 | #Create Visualization of Currency Exchange Rate Value - Over Time 124 | #Determine Cycle number (when data is taken) and time when taken 125 | for k in range(0,cycle_num): 126 | i=0 127 | exch_rate_list = [] 128 | print("Cycle Number: ", k) 129 | for sym in arb_list: 130 | print(sym) 131 | if sym in symbols: 132 | depth = exchange1.fetch_order_book(symbol=sym) 133 | #pprint(depth) 134 | if i % 2 == 0: 135 | exch_rate_list.append(depth['bids'][0][0]) 136 | else: 137 | exch_rate_list.append(depth['asks'][0][0]) 138 | i+=1 139 | else: 140 | exch_rate_list.append(0) 141 | #exch_rate_list.append(((rateB[-1]-rateA[-1])/rateA[-1])*100) #Expected Profit 142 | exch_rate_list.append(time.time()) #change to Human Readable time 143 | print(exch_rate_list) 144 | #Compare to determine if Arbitrage opp exists 145 | if exch_rate_list[0]0: 257 | break #Break Out of Statement 258 | exch = getattr (ccxt, exch1) () 259 | #print(gdax) 260 | #Secondary Method to Set Exchange 261 | #exchange1 = ccxt.binance() 262 | #exchange1_info = dir(exch) 263 | #pprint(exchange1_info) 264 | print("\n\nExchange: ", exch.id) 265 | print("Set Exchange Info (Limits): ", exch.rateLimit) 266 | print("Load Market: ", exch.load_markets) 267 | #print(list(exchange1.markets.keys())) 268 | symbols = exch.symbols 269 | if symbols is None: 270 | print("\n-----------------\nNo symbols Loaded\n-----------------") 271 | else: 272 | print("-----------------------\nNumber of Symbols: ", len(symbols)) 273 | print("Exchange & Symbols:") 274 | #print(exchange1.id, exchange1.markets.keys()) 275 | print(exch.id,"- ", symbols) 276 | print("-----------------------") 277 | for sym in symbols: 278 | list_of_symbols.append(sym) #Create List of Symbols - Each Exchange 279 | all_symbols.append(sym) #Create List of ALL Symbols on ALL Exchanges 280 | #print("\n\n'Fetch Orders: ", exchange1.fetch_orders()) 281 | currencies = exch.currencies 282 | #print("Currencies: ", currencies) 283 | time.sleep(5) 284 | 285 | #Get Market Depth 286 | #for symbol in list_of_symbols: 287 | #market_depth(symbol) 288 | #Test Market Order - Visualize - Scalping Functions: Testing with random coin of each exchange 289 | rand_sym = random.choice(list_of_symbols) 290 | market_depth(rand_sym, exch) 291 | visualize_market_depth(sym=rand_sym, exchange=exch) 292 | scalping_orders(exch, rand_sym) 293 | i+=1 #Break Out of Initialize Statement 294 | time.sleep(4) 295 | 296 | """for symbol in exch.markets: 297 | print("Order Book for Symbol: ", symbol) 298 | print (exch.fetch_order_book (symbol)) 299 | time.sleep (3)""" 300 | 301 | #Place a test market buy order, to place an actual order use the create_order function 302 | 303 | #Get Info about Coins in Watch List 304 | #coin_prices(list_of_symbols) 305 | #coin_tickers(list_of_symbols) 306 | 307 | #for coin in micro_cap_coins: 308 | # visualize_market_depth(1, 1, coin) 309 | 310 | #for coin in micro_cap_coins: 311 | # scalping_orders(coin, 1, 1) 312 | 313 | #Get recent trades 314 | #trades = client.get_recent_trades(symbol='BNBBTC') 315 | #print("\nRecent Trades: ", trades) 316 | #print("Local Time: ", time.localtime()) 317 | #print("Recent Trades Time: ", convert_time_binance(trades[0]['time'])) 318 | 319 | #Get historical trades 320 | #hist_trades = client.get_historical_trades(symbol='BNBBTC') 321 | #print("\nHistorical Trades: ", hist_trades) 322 | 323 | #Get aggregate trades 324 | #agg_trades = client.get_aggregate_trades(symbol='BNBBTC') 325 | #print("\nAggregate Trades: ", agg_trades) 326 | 327 | #Example Visualizations of Coins 328 | """save_historical_data_Roibal.save_historic_klines_csv('BTCUSDT', "1 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_1MINUTE) 329 | save_historical_data_Roibal.save_historic_klines_csv('ETHBTC', "6 months ago UTC", "now UTC", Client.KLINE_INTERVAL_1DAY) 330 | save_historical_data_Roibal.save_historic_klines_csv('BRDBNB', "8 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_3MINUTE) 331 | save_historical_data_Roibal.save_historic_klines_csv('BTCUSDT', "12 months ago UTC", "now UTC", Client.KLINE_INTERVAL_1WEEK) 332 | save_historical_data_Roibal.save_historic_klines_csv('ETHUSDT', "8 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_15MINUTE) 333 | 334 | #Visualize All Micro Cap Coins for 8 hour period and 3 minute Candlestick 335 | for coin in micro_cap_coins: 336 | save_historical_data_Roibal.save_historic_klines_csv(coin, "8 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_3MINUTE) 337 | save_historical_data_Roibal.save_historic_klines_csv(coin, "24 hours ago UTC", "now UTC", Client.KLINE_INTERVAL_15MINUTE) 338 | save_historical_data_Roibal.save_historic_klines_csv(coin, "1 month ago UTC", "now UTC", Client.KLINE_INTERVAL_1DAY) 339 | """ 340 | print("INITIALIZE SUCCESSFUL") 341 | except(): 342 | print("\n \n \nATTENTION: NON-VALID CONNECTION WITH CRYPTOCURRENCY BOT \n \n \n") 343 | 344 | #Account Withdrawal History Info 345 | #withdraws = client.get_withdraw_history() 346 | #print("\nClient Withdraw History: ", withdraws) 347 | 348 | 349 | def market_depth(sym, exchange=ccxt.binance(), num_entries=20): 350 | #Get market depth 351 | #Retrieve and format market depth (order book) including time-stamp 352 | i=0 #Used as a counter for number of entries 353 | print("Order Book: ") #convert_time_binance(client.get_server_time())) #Transfer to CCXT 354 | exchange.verbose = True 355 | depth = exchange.fetch_order_book(symbol=sym) #Transf'd to CCXT 356 | #pprint(depth) 357 | print(depth['asks'][0]) 358 | ask_tot=0.0 359 | ask_price =[] 360 | ask_quantity = [] 361 | bid_price = [] 362 | bid_quantity = [] 363 | bid_tot = 0.0 364 | place_order_ask_price = 0 365 | place_order_bid_price = 0 366 | max_order_ask = 0 367 | max_order_bid = 0 368 | print("\n", sym, "\nDepth ASKS:\n") #Edit to work with CCXT 369 | print("Price Amount") 370 | for ask in depth['asks']: 371 | if ifloat(max_order_ask): 373 | #Determine Price to place ask order based on highest volume 374 | max_order_ask=ask[1] 375 | #print("Max Order ASK: ", max_order_ask) 376 | place_order_ask_price=round(float(ask[0]),5)-0.0001 377 | #ask_list.append([ask[0], ask[1]]) 378 | ask_price.append(float(ask[0])) 379 | ask_tot+=float(ask[1]) 380 | ask_quantity.append(ask_tot) 381 | #print(ask) 382 | i+=1 383 | j=0 #Secondary Counter for Bids 384 | print("\n", sym, "\nDepth BIDS:\n") 385 | print("Price Amount") 386 | for bid in depth['bids']: 387 | if jfloat(max_order_bid): 389 | #Determine Price to place ask order based on highest volume 390 | max_order_bid=bid[1] 391 | #print("Max Order BID: ", max_order_bid) 392 | place_order_bid_price=round(float(bid[0]),5)+0.0001 393 | bid_price.append(float(bid[0])) 394 | bid_tot += float(bid[1]) 395 | bid_quantity.append(bid_tot) 396 | #print(bid) 397 | j+=1 398 | return ask_price, ask_quantity, bid_price, bid_quantity, place_order_ask_price, place_order_bid_price 399 | #Plot Data 400 | 401 | def scalping_orders(exchange = ccxt.binance(), coin='BTC/USDT', wait=1, tot_time=1): 402 | #Function for placing 'scalp orders' 403 | #Calls on Visualizing Scalping Orders Function 404 | ap, aq, bp, bq, place_ask_order, place_bid_order, spread, proj_spread, max_bid, min_ask = visualize_market_depth(wait, tot_time, coin, 5, exchange) 405 | print("Coin: {}\nPrice to Place Ask Order: {}\nPrice to place Bid Order: {}".format(coin, place_ask_order, place_bid_order)) 406 | print("Spread: {} % Projected Spread {} %".format(spread, proj_spread)) 407 | print("Max Bid: {} Min Ask: {}".format(max_bid, min_ask)) 408 | #Place Orders based on calculated bid-ask orders if projected > 0.05% (transaction fee) 409 | #Documentation: http://python-binance.readthedocs.io/en/latest/account.html#orders 410 | """ 411 | if proj_spread > 0.05: 412 | quant1=100 #Determine Code Required to calculate 'minimum' quantity 413 | #Place Bid Order: 414 | bid_order1 = client.order_limit_buy( 415 | symbol=coin, 416 | quantity=quant1, 417 | price=place_bid_order) 418 | #Place Ask Order 419 | ask_order1 = client.order_limit_sell( 420 | symbol=coin, 421 | quantity=quant1, 422 | price=place_ask_order) 423 | 424 | 425 | #Place second order if current spread > 0.05% (transaction fee) 426 | 427 | """ 428 | 429 | 430 | def visualize_market_depth(wait_time_sec='1', tot_time='1', sym='BTC/USDT', precision=5, exchange=ccxt.binance()): 431 | cycles = int(tot_time)/int(wait_time_sec) 432 | start_time = time.asctime() #Trans CCXT 433 | fig, ax = plt.subplots() 434 | for i in range(1,int(cycles)+1): 435 | ask_pri, ask_quan, bid_pri, bid_quan, ask_order, bid_order = market_depth(sym, exchange) 436 | 437 | #print(ask_price) 438 | plt.plot(ask_pri, ask_quan, color = 'red', label='asks-cycle: {}'.format(i)) 439 | plt.plot(bid_pri, bid_quan, color = 'blue', label = 'bids-cycle: {}'.format(i)) 440 | 441 | #ax.plot(depth['bids'][0], depth['bids'][1]) 442 | max_bid = max(bid_pri) 443 | min_ask = min(ask_pri) 444 | max_quant = max(ask_quan[-1], bid_quan[-1]) 445 | spread = round(((min_ask-max_bid)/min_ask)*100,5) #Spread based on market 446 | proj_order_spread = round(((ask_order-bid_order)/ask_order)*100, precision) 447 | price=round(((max_bid+min_ask)/2), precision) 448 | plt.plot([price, price],[0, max_quant], color = 'green', label = 'Price - Cycle: {}'.format(i)) #Vertical Line for Price 449 | plt.plot([ask_order, ask_order],[0, max_quant], color = 'black', label = 'Ask - Cycle: {}'.format(i)) 450 | plt.plot([bid_order, bid_order],[0, max_quant], color = 'black', label = 'Buy - Cycle: {}'.format(i)) 451 | #plt.plot([min_ask, min_ask],[0, max_quant], color = 'grey', label = 'Min Ask - Cycle: {}'.format(i)) 452 | #plt.plot([max_bid, max_bid],[0, max_quant], color = 'grey', label = 'Max Buy - Cycle: {}'.format(i)) 453 | ax.annotate("Max Bid: {} \nMin Ask: {}\nSpread: {} %\nCycle: {}\nPrice: {}" 454 | "\nPlace Bid: {} \nPlace Ask: {}\n Projected Spread: {} %".format(max_bid, min_ask, spread, i, price, bid_order, ask_order, proj_order_spread), 455 | xy=(max_bid, ask_quan[-1]), xytext=(max_bid, ask_quan[0])) 456 | if i==(cycles+1): 457 | break 458 | else: 459 | time.sleep(int(wait_time_sec)) 460 | #end_time = time.asctime() 461 | ax.set(xlabel='Price', ylabel='Quantity', 462 | title='{} Order Book: {} \n {}\n Cycle Time: {} seconds - Num Cycles: {}'.format(exchange.id, sym, start_time, wait_time_sec, cycles)) 463 | plt.legend() 464 | plt.show() 465 | return ask_pri, ask_quan, bid_pri, bid_quan, ask_order, bid_order, spread, proj_order_spread, max_bid, min_ask 466 | 467 | 468 | def coin_prices(watch_list): 469 | #Will print to screen, prices of coins on 'watch list' 470 | #returns all prices 471 | prices = client.get_all_tickers() #Trans CCXT 472 | print("\nSelected (watch list) Ticker Prices: ") 473 | for price in prices: 474 | if price['symbol'] in watch_list: 475 | print(price) 476 | return prices 477 | 478 | 479 | def coin_tickers(watch_list): 480 | # Prints to screen tickers for 'watch list' coins 481 | # Returns list of all price tickers 482 | tickers = client.get_orderbook_tickers() #Trans CCXT 483 | print("\nWatch List Order Tickers: \n") 484 | for tick in tickers: 485 | if tick['symbol'] in watch_list: 486 | print(tick) 487 | return tickers 488 | 489 | def portfolio_management(deposit = '10000', withdraw=0, portfolio_amt = '0', portfolio_type='USDT', test_acct='True'): 490 | """The Portfolio Management Function will be used to track profit/loss of Portfolio in Any Particular Currency (Default: USDT)""" 491 | #Maintain Portfolio Statistics (Total Profit/Loss) in a file 492 | pass 493 | 494 | def Bollinger_Bands(): 495 | #This Function will calculate Bollinger Bands for Given Time Period 496 | pass 497 | 498 | def buy_sell_bot(): 499 | pass 500 | 501 | def position_sizing(): 502 | pass 503 | 504 | def trailing_stop_loss(): 505 | pass 506 | 507 | if __name__ == "__main__": 508 | run() 509 | -------------------------------------------------------------------------------- /Historic-Legacy/Private_TriArbBot.py: -------------------------------------------------------------------------------- 1 | """ 2 | The Purpose of the PrivateBinance Arbitrage Bot (based on RoibalBot) Python Program is to create an automated trading bot (functionality) on Binance 3 | Utilized Python-Binance ( https://github.com/sammchardy/python-binance ) 4 | Advanced-Version capable of all exchanges, all coins (using cctx) 5 | 6 | This 'bot' will run a functionality which seeks profitable triangular arbitrage opportunities on Binance 7 | Weekly/Daily/Hourly reports created on profit/loss 8 | 9 | Instructional Youtube Video: https://www.youtube.com/watch?v=8AAN03M8QhA - Additional Videos Available on youtube 10 | 11 | Created 4/14/2018 by Joaquin Roibal 12 | V 0.01 - Updated 4/20/2018 13 | v 0.02 - Updated 5/30/2018 - Converted to Advanced Version: https://github.com/Roibal/Cryptocurrency-Trading-Bots-Python-Beginner-Advance 14 | v 0.03 - Created 6/18/2018 - Binance Arbitrage Bot 15 | v 0.04 - 6/21/2018 - Changed Name to CryptoTriangularArbitrageBinanceBot.py 16 | v 1.00 - 6/24/2018 - Converted to Private_TriArbBot.py for Private Trader Group 17 | 18 | All Rights Reserved 19 | 20 | ATTENION: BY RUNNING SCRIPT YOU AGREE TO REMIT 1% of PROFITS TO THE FOLLOWING ADDRESS: 21 | BTC: 1BYrAED4pi5DMKu2qZPv8pwe6rEeuxoCiD 22 | 23 | NOTE: All Subsequent Version of Program must contain this message, unmodified, in it's entirety 24 | Copyright (c) 2018 by Joaquin Roibal 25 | """ 26 | 27 | from binance.client import Client 28 | from binance.enums import * 29 | import time 30 | from datetime import datetime 31 | import matplotlib 32 | from matplotlib import cm 33 | import matplotlib.pyplot as plt 34 | from binance.enums import * 35 | import pprint 36 | #import save_historical_data_Roibal 37 | from BinanceKeys import BinanceKey1 38 | 39 | """ 40 | api_key = BinanceKey1['api_key'] 41 | api_secret = BinanceKey1['api_secret'] 42 | 43 | client = Client(api_key, api_secret) 44 | """ 45 | 46 | #Found Code To Remove 1000ms error - https://github.com/sammchardy/python-binance/issues/249 47 | class Binance: 48 | def __init__(self, public_key = '', secret_key = '', sync = False): 49 | self.time_offset = -3199 50 | self.b = Client(public_key, secret_key) 51 | 52 | if 1: 53 | self.time_offset = self._get_time_offset() 54 | 55 | def _get_time_offset(self): 56 | res = self.b.get_server_time() 57 | print(res['serverTime'] - int(time.time() * 1000)) 58 | return res['serverTime'] - int(time.time() * 1000) 59 | 60 | def synced(self, fn_name, **args): 61 | args['timestamp'] = int(time.time() - self.time_offset) 62 | return getattr(self.b, fn_name)(**args) 63 | 64 | client = Binance(public_key = BinanceKey1['api_key'], secret_key = BinanceKey1['api_secret'], sync=True) 65 | print(client) 66 | #client.synced('order_market_buy', symbol='BNBBTC', quantity=10) 67 | 68 | 69 | def run(): 70 | #Initialize Arbitrage Binance Bot 71 | initialize_arb() 72 | #Get Binance Wallet Balance - Split into 4 coins evenly 73 | 74 | #Perform our Arbitrage Function 75 | 76 | #Data Output (log) in a text file - keep track of start/end time, trades, balance 77 | pass 78 | 79 | def initialize_arb(): 80 | 81 | welcome_message = "\n\n---------------------------------------------------------\n\n" 82 | welcome_message+= "Hello and Welcome to the Binance Arbitrage Crypto Trader Bot Python Script\nCreated 2018 by Joaquin Roibal (@BlockchainEng)" 83 | welcome_message+= "A quick 'run-through' will be performed to introduce you to the functionality of this bot\n" 84 | welcome_message+="To learn more visit medium.com/@BlockchainEng or watch introductory Youtube Videos" 85 | welcome_message+="\nCopyright 2018 by Joaquin Roibal\n" 86 | bot_start_time = str(datetime.now()) 87 | welcome_message+= "\nBot Start Time: {}\n\n\n".format(bot_start_time) 88 | client.synced('get_account') #Example of using Sync'd 89 | print(welcome_message) 90 | #info = client.synced.get_account() 91 | #pprint(info) 92 | balance = client.synced('get_asset_balance', asset='BTC') 93 | pprint(balance) 94 | data_log_to_file(balance) 95 | 96 | #output to file - create function 97 | data_log_to_file(welcome_message) 98 | time.sleep(5) 99 | try: 100 | status = Client.synced('get_system_status()') 101 | #print("\nExchange Status: ", status) 102 | 103 | #Account Withdrawal History Info 104 | withdraws = Client.synced('get_withdraw_history()') 105 | #print("\nClient Withdraw History: ", withdraws) 106 | 107 | #for symbol in list_of_symbols: 108 | #market_depth(symbol) 109 | #Collect all Symbols for Exchange 110 | #Find Arbitrage Opportunities 111 | coin_list = ['BTC', 'ETH', 'USDT', 'BNB'] 112 | list_of_symbols = ['ETHBTC', 'BNBETH', 'BNBBTC'] 113 | list_of_symbols2 = ['ETHUSDT', 'BNBETH', 'BNBUSDT'] 114 | list_of_symbols3 = ['BTCUSDT', 'BNBBTC', 'BNBUSDT'] 115 | list_of_arb_sym = [list_of_symbols, list_of_symbols2, list_of_symbols3] 116 | #for sym in list_of_symbols: 117 | #info = client.get_symbol_info(sym) 118 | #print(info) 119 | #prices = client.get_all_tickers() 120 | tickers = client.get_orderbook_tickers() 121 | #print(prices) 122 | #print(tickers) 123 | #portfolio = [10, 100, 10000, 500, str(datetime.now())] #Number of: [Bitcoin, Ethereum, USDT, Binance Coin] 124 | #Load Binance Portfolio 125 | binance_portfolio(coin_list) 126 | #Load Portfolio File 127 | portfolio=[] 128 | with open('Portfolio.txt') as f1: 129 | read_data = f1.readlines() 130 | for line in read_data: 131 | load_portfolio = line #Load Previous Portfolio 132 | load_portfolio = list(load_portfolio[1:-1].split(',')) 133 | #print(load_portfolio) 134 | #time.sleep(5) 135 | #for i in range(0,3): 136 | #portfolio[i] = float(portfolio[i]) #Set Type for first 4 values of Portfolio 137 | i=0 138 | for val in load_portfolio: 139 | #print(val.strip()) 140 | if i == 4: 141 | portfolio.append(str(datetime.now())) 142 | break 143 | portfolio.append(float(val)) 144 | i+=1 145 | portf_msg = "Starting Portfolio (Paper): " + str(portfolio) 146 | #Load Balances for each coin in exchange 147 | #Split BTC into 4 equal amounts, buy all 3 other coins with that amount 148 | print(portf_msg) 149 | portf_file_save(portfolio) 150 | data_log_to_file(portf_msg) 151 | while 1: 152 | #Run Arbitrage Profit Functionality - To Determine Highest Profit Percentage - Cont Loop 153 | calc_profit_list =[] 154 | for arb_market in list_of_arb_sym: 155 | calc_profit_list.append(arbitrage_bin(arb_market, tickers, portfolio, 1, 1)) 156 | 157 | for profit1 in calc_profit_list: 158 | data_log_to_file(str(profit1)) 159 | print(calc_profit_list) 160 | exp_profit = 0 #Expected Profit, Set to 0 initially 161 | m = n = 0 #Market Position Market 162 | for exch_market in calc_profit_list: 163 | if exch_market[4]>exp_profit: 164 | exp_profit = exch_market[4] 165 | m = n 166 | n+=1 167 | profit_message = "\nMost Profitable Market: {} \nExpected Profit: {}%".format(list_of_arb_sym[m], exp_profit) 168 | print(profit_message) 169 | data_log_to_file(profit_message) 170 | time.sleep(5) 171 | #Run Arbitrage Function on Highest Profit Percentage Coin for 10 minutes 172 | arb_list_data = [] 173 | arb_start_time = str(datetime.now()) 174 | for i in range(0,10): 175 | #Collect Arbitrage Data Into List format for 5 cycles, 30 second cycles (replaces functionality) 176 | 177 | try: 178 | arb_list_data.append(arbitrage_bin(list_of_arb_sym[m], tickers, portfolio, 1, 1, 'Yes', 'Yes')) #'Yes' to place orders 179 | binance_portfolio(coin_list) 180 | except: 181 | raise 182 | pass 183 | #print(arb_list_data) 184 | time.sleep(15) 185 | arb_end_time = str(datetime.now()) 186 | #Visualize Collected Arb List Data with MatPlotLib 187 | viz_arb_data(arb_list_data, list_of_arb_sym[m], arb_start_time, arb_end_time) 188 | except: 189 | print("\nFAILURE INITIALIZE\n") 190 | raise 191 | 192 | def binance_portfolio(coin_list): 193 | binance_portfolio = [] 194 | for curr in coin_list: 195 | balance = client.synced('get_asset_balance', asset=curr) 196 | binance_portfolio.append(balance) 197 | data_log_to_file(binance_portfolio) 198 | portf_file_save(binance_portfolio, 'RealBinancePortfolio.txt') 199 | 200 | def data_log_to_file(message): 201 | with open('CryptoTriArbBot_DataLog.txt', 'a+') as f: 202 | f.write(message) 203 | 204 | def portf_file_save(portfolio, portf_file='Portfolio.txt' ): 205 | with open(portf_file, 'a+') as f: 206 | f.write('\n'+str(portfolio)) 207 | 208 | def arbitrage_bin(list_of_sym, tickers, portfolio, cycle_num=10, cycle_time=30, place_order='No', real_order='No'): 209 | #Create Triangular Arbitrage Function 210 | arb_message = "Beginning Binance Arbitrage Function Data Collection - Running\n" 211 | print(arb_message) 212 | data_log_to_file(arb_message) 213 | #time.sleep(2) 214 | fee_percentage = 0.05*3 #divided by 100 215 | #Created Arbitrage Functionality for with Python-Binance 216 | for i in range(0,1): #initialize Exchange 217 | #create blacklist of exchanges 218 | 219 | #exchange1 = getattr (ccxt, exch) () 220 | #symbols = tickers.keys() 221 | #print(symbols) 222 | #time.sleep(20) 223 | #Find Pairs to Trade 224 | """ 225 | pairs = [] 226 | for sym in symbols: 227 | for symbol in coins: 228 | if symbol in sym: 229 | pairs.append(sym) 230 | print(pairs) 231 | #From Coin 1 to Coin 2 - ETH/BTC - Bid 232 | #From Coin 2 to Coin 3 - ETH/LTC - Ask 233 | #From Coin 3 to Coin 1 - BTC/LTC - Bid 234 | arb_list = ['ETH/BTC'] #, 'ETH/LTC', 'BTC/LTC'] 235 | #Find 'closed loop' of currency rate pairs 236 | j=0 237 | while 1: 238 | if j == 1: 239 | final = arb_list[0][-3:] + '/' + str(arb_list[1][-3:]) 240 | print(final) 241 | #if final in symbols: 242 | arb_list.append(final) 243 | break 244 | for sym in symbols: 245 | if sym in arb_list: 246 | pass 247 | else: 248 | if j % 2 == 0: 249 | if arb_list[j][0:3] == sym[0:3]: 250 | if arb_list[j] == sym: 251 | pass 252 | else: 253 | arb_list.append(sym) 254 | print(arb_list) 255 | j+=1 256 | break 257 | if j % 2 == 1: 258 | if arb_list[j][-3:] == sym[-3:]: 259 | if arb_list[j] == sym: 260 | pass 261 | else: 262 | arb_list.append(sym) 263 | print(arb_list) 264 | j+=1 265 | break 266 | """ 267 | #time.sleep(.5) 268 | print("List of Arbitrage Symbols:", list_of_sym) 269 | #time.sleep(3) 270 | #Determine Rates for our 3 currency pairs - order book 271 | list_exch_rate_list = [] 272 | if 1: 273 | #Create Visualization of Currency Exchange Rate Value - Over Time 274 | #Determine Cycle number (when data is taken) and time when taken 275 | for k in range(0,cycle_num): 276 | i=0 277 | exch_rate_list = [] 278 | data_collect_message1 = "Data Collection Cycle Number: "+str(k) +'\n' 279 | #print(data_collect_message1) 280 | data_log_to_file(data_collect_message1) 281 | for sym in list_of_sym: 282 | currency_pair = "Currency Pair: "+str(sym)+" " 283 | if sym in list_of_sym: 284 | #depth = client.get_(sym) 285 | #print(depth) 286 | """if i == 0: #For first in triangle 287 | depth = client.get_order_book(symbol=sym) 288 | exch_rate_list.append(float(depth['bids'][0][0])) 289 | print(depth['bids'][0][0]) 290 | """ 291 | if i % 2==0: 292 | #exch_rate_list.append(depth['bids'][0][0]) #converted to Binance 293 | depth = client.get_order_book(symbol=sym) 294 | inv1 = depth['asks'][0][0] 295 | exch_rate_list.append(float(inv1)) #Inverse Because of Binance Format 296 | Exch_rate1 = currency_pair+ "Exchange Rate: {}".format(depth['asks'][0][0]) +' ' 297 | print(Exch_rate1) 298 | data_log_to_file(Exch_rate1) 299 | if i == 1: 300 | #exch_rate_list.append(depth['asks'][0][0]) 301 | depth = client.get_order_book(symbol=sym) 302 | inv2 = round(1.0/float(depth['bids'][0][0]),6) 303 | exch_rate_list.append(float(inv2)) #Inverse because Binance Format 304 | Exch_rate2 = currency_pair+"Exchange Rate: {}".format(depth['bids'][0][0])+' ' 305 | print(Exch_rate2) 306 | data_log_to_file(Exch_rate2) 307 | i+=1 308 | else: 309 | exch_rate_list.append(0) 310 | 311 | #exch_rate_list.append(((rateB[-1]-rateA[-1])/rateA[-1])*100) #Expected Profit 312 | exch_rate_list.append(datetime.now()) #changed to Human Readable time 313 | #time.sleep(10) 314 | #Compare to determine if Arbitrage opp exists 315 | rate1 = exch_rate_list[0] 316 | buy_price = "Buy: {}".format(rate1) 317 | print(buy_price) 318 | data_log_to_file(buy_price) 319 | rate2 = float(exch_rate_list[2])*float(exch_rate_list[1]) 320 | sell_price = "Sell: {}".format(rate2) 321 | print(sell_price) 322 | data_log_to_file(sell_price) 323 | if float(rate1)fee_percentage: 341 | real_order_msg = "ENTERING REAL ORDER: " 342 | real_order_msg += "NO FEE PROFIT PERCENTAGE: "+str(arb_profit) 343 | real_order_msg += "FEE PERCENTAGE: "+str(fee_percentage) 344 | print(real_order_msg) 345 | data_log_to_file(real_order_msg) 346 | #Place 3 orders in succession buying/selling coins for the tri arb 347 | for a, sym in enumerate(list_of_sym): 348 | i=0 349 | quantity = [0.01, .1, 10, 1] #Limit Amounts For Trading 350 | if i==0: 351 | order = client.synced('create_order', 352 | symbol=sym, 353 | side=SIDE_BUY, 354 | type=ORDER_TYPE_LIMIT, 355 | timeInForce=15, 356 | quantity=quantity[int(a)], 357 | price=float(exch_rate_list[int(a)])) 358 | i+=1 359 | else: 360 | order = client.synced('create_order', 361 | symbol=sym, 362 | side=SIDE_SELL, 363 | type=ORDER_TYPE_LIMIT, 364 | timeInForce=15, 365 | quantity=quantity[int(a)], 366 | price=float(exch_rate_list[int(a)])) 367 | print("Placing Order: ", str(order)) 368 | plc_order_msg = "Placing Order: "+ str(order) 369 | portf_file_save(plc_order_msg, 'PlaceOrderLog.txt') 370 | data_log_to_file(plc_order_msg) 371 | #Call function that will paper-trade with portfolio 372 | #portfolio = list(portfolio) 373 | portfolio = tri_arb_paper(portfolio, list_of_sym, exch_rate_list) 374 | portf_file_save(portfolio) 375 | else: 376 | arb_2_msg = "No Arbitrage Possibility" 377 | print(arb_2_msg) 378 | data_log_to_file(arb_2_msg) 379 | #Add 0 for profit to list 380 | exch_rate_list.append(0) 381 | exch_msg = "Exchange Rate List: " +str(exch_rate_list)+'\n' 382 | #for exch_list in exch_rate_list: 383 | #print(exch_msg) 384 | data_log_to_file(exch_msg) 385 | #Format data (list) into List format (list of lists) 386 | #list_exch_rate_list.append(exch_rate_list) 387 | time.sleep(cycle_time) 388 | #print(list_exch_rate_list) 389 | print('\nARBITRAGE FUNCTIONALITY SUCCESSFUL - Data of Exchange Rates Collected\n') 390 | return exch_rate_list 391 | 392 | def tri_arb_paper(portfolio1, sym_list, list_exch_rates): 393 | #Determine Which Coin Starting With 394 | tri_arb_paper_msg = "\nSTARTING TRI ARB PAPER TRADING FUNCTION\n" 395 | print(tri_arb_paper_msg) 396 | #print(portfolio1) 397 | time.sleep(10) 398 | data_log_to_file(tri_arb_paper_msg) 399 | if sym_list[0][-3:]=='BTC': 400 | portf_pos = 0 401 | elif sym_list[0][-3:]=='ETH': 402 | portf_pos = 1 403 | elif sym_list[0][-3:]=='SDT': 404 | portf_pos = 2 405 | elif sym_list[0][-3:]=='BNB': 406 | portf_pos = 3 407 | start_amount = float(portfolio1[portf_pos]) 408 | amt_coin2 = start_amount / float(list_exch_rates[0]) 409 | amt_coin3 = amt_coin2 * float(list_exch_rates[1]) 410 | final_amount = amt_coin3 * float(list_exch_rates[2]) 411 | tri_arb_paper_msg = "Starting Amount: "+str(sym_list[0][-3:])+" "+str(start_amount)+' ' 412 | #Buy Currency 2 with Currency 1 413 | tri_arb_paper_msg += "Amount Coin 2: "+str(sym_list[0][0:3])+" "+str(amt_coin2)+' ' 414 | #Buy Currency 3 with Currency 2 415 | tri_arb_paper_msg += "Amount Coin 3: "+str(sym_list[2][0:3])+" "+str(amt_coin3) +' ' 416 | #Buy Currency 1 with Currency 3 417 | tri_arb_paper_msg += "Final Amount: "+str(sym_list[0][-3:])+" "+str(final_amount)+' ' 418 | print(tri_arb_paper_msg) 419 | data_log_to_file(tri_arb_paper_msg) 420 | portfolio1[portf_pos] = final_amount 421 | portfolio1[-1] = str(datetime.now()) 422 | return portfolio1 423 | 424 | def viz_arb_data(list_exch_rate_list, arb_market, start_time, end_time): 425 | viz_msg = "RUNNING ARBITRAGE VISUALIZATION FUNCTIONALITY" 426 | print(viz_msg) 427 | data_log_to_file(viz_msg) 428 | #Visualize with Matplotlib 429 | #use matplotlib to plot data 430 | #Create list from Lists for matplotlib format 431 | rateA = [] #Original Exchange Rate 432 | rateB = [] #Calculated/Arbitrage Exchange Rate 433 | rateB_fee = [] #Include Transaction Fee 434 | price1 = [] #List for Price of Token (Trade) 1 435 | price2 = [] #List for price of Token (Trade) 2 436 | time_list = [] #time of data collection 437 | profit_list = [] #Record % profit 438 | for rate in list_exch_rate_list: 439 | rateA.append(rate[0]) 440 | rateB1 = round(float(rate[1])*float(rate[2]),6) 441 | rateB.append(rateB1) #Multiplied together because of Binance Format 442 | #rateB_fee.append((rate[1]/rate[2])*(1-fee_percentage)*(1-fee_percentage)) 443 | price1.append(rate[1]) 444 | price2.append(rate[2]) 445 | profit_list.append(rate[4]) 446 | time_list.append(rate[3]) 447 | viz_msg2 = "Rate A: {} \n Rate B: {} \n Projected Profit (%): {} ".format(rateA, rateB, profit_list) #rateB_fee)) 448 | print(viz_msg2) 449 | data_log_to_file(viz_msg2) 450 | 451 | #from https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot 452 | #Extended 3 axis functionality - https://matplotlib.org/gallery/ticks_and_spines/multiple_yaxis_with_spines.html#sphx-glr-gallery-ticks-and-spines-multiple-yaxis-with-spines-py 453 | #fig, ax = plt.subplots() 454 | fig, host = plt.subplots() 455 | fig.subplots_adjust(right=0.75) 456 | 457 | par1 = host.twinx() 458 | par2 = host.twinx() 459 | par2.spines["right"].set_position(("axes", 1.2)) 460 | make_patch_spines_invisible(par2) 461 | par2.spines["right"].set_visible(True) 462 | #Graph Rate & Calculated Rate on Left Hand Side 463 | p1, = host.plot(time_list, rateA, "k", label = "{}".format(arb_market[0])) 464 | p1, = host.plot(time_list, rateB, "k+", label = "{} * {}".format(arb_market[1], arb_market[2])) 465 | #p1, = host.plot(time_list, rateB_fee, 'k+', label = "{} / {} - with Fee".format(arb_list[1], arb_list[2])) 466 | #Graph Exchange Rate (Originals) 467 | p2, = par1.plot(time_list, price1, "b-", label="Price - {}".format(arb_market[1])) 468 | p3, = par2.plot(time_list, price2, "g-", label="Price - {}".format(arb_market[2])) 469 | #show our graph - with labels 470 | host.set_xlabel("Time") 471 | host.set(title='Triangular Arbitrage - Exchange: {}\nStart Time: {}\n End Time: {}\n' 472 | 'Copyright (c) 2018 @BlockchainEng'.format('Binance', start_time, end_time)) 473 | host.set_ylabel("Exchange Rate") 474 | par1.set_ylabel("Price - {}".format(arb_market[1])) 475 | par2.set_ylabel("Price - {}".format(arb_market[2])) 476 | host.yaxis.label.set_color(p1.get_color()) 477 | tkw = dict(size=4, width=1.5) 478 | host.tick_params(axis='y', colors=p1.get_color(), **tkw) 479 | par1.tick_params(axis='y', colors=p2.get_color(), **tkw) 480 | par2.tick_params(axis='y', colors=p3.get_color(), **tkw) 481 | host.tick_params(axis='x', **tkw) 482 | 483 | lines = [p1, p2, p3] 484 | host.legend(lines, [l.get_label() for l in lines]) #show Legend 485 | fname = "Binance_Test.png" #+"-"+str(arb_market[0])+str(arb_market[1])+str(arb_market[2])+".png" 486 | #Future: Include Start/End Time 487 | plt.savefig(fname) #Changes to make - Format 488 | """, dpi=None, facecolor='w', edgecolor='w', 489 | orientation='portrait', papertype=None, format=None, 490 | transparent=False, bbox_inches=None, pad_inches=0.1, 491 | frameon=None)""" 492 | print_figure_message = "Data Collected Figure Printed & Saved - " + str(fname) 493 | print(print_figure_message) 494 | data_log_to_file(print_figure_message) 495 | #plt.show() 496 | 497 | def make_patch_spines_invisible(ax): 498 | ax.set_frame_on(True) 499 | ax.patch.set_visible(False) 500 | for sp in ax.spines.values(): 501 | sp.set_visible(False) 502 | 503 | 504 | """ 505 | def market_depth(sym, num_entries=20): 506 | #Get market depth 507 | #Retrieve and format market depth (order book) including time-stamp 508 | i=0 #Used as a counter for number of entries 509 | #print("Order Book: ", convert_time_binance(client.get_server_time())) 510 | depth = client.get_order_book(symbol=sym) 511 | print(depth) 512 | print(depth['asks'][0]) 513 | ask_tot=0.0 514 | ask_price =[] 515 | ask_quantity = [] 516 | bid_price = [] 517 | bid_quantity = [] 518 | bid_tot = 0.0 519 | place_order_ask_price = 0 520 | place_order_bid_price = 0 521 | max_order_ask = 0 522 | max_order_bid = 0 523 | print("\n", sym, "\nDepth ASKS:\n") 524 | print("Price Amount") 525 | for ask in depth['asks']: 526 | if ifloat(max_order_ask): 528 | #Determine Price to place ask order based on highest volume 529 | max_order_ask=ask[1] 530 | place_order_ask_price=round(float(ask[0]),5)-0.0001 531 | #ask_list.append([ask[0], ask[1]]) 532 | ask_price.append(float(ask[0])) 533 | ask_tot+=float(ask[1]) 534 | ask_quantity.append(ask_tot) 535 | #print(ask) 536 | i+=1 537 | j=0 #Secondary Counter for Bids 538 | print("\n", sym, "\nDepth BIDS:\n") 539 | print("Price Amount") 540 | for bid in depth['bids']: 541 | if jfloat(max_order_bid): 543 | #Determine Price to place ask order based on highest volume 544 | max_order_bid=bid[1] 545 | place_order_bid_price=round(float(bid[0]),5)+0.0001 546 | bid_price.append(float(bid[0])) 547 | bid_tot += float(bid[1]) 548 | bid_quantity.append(bid_tot) 549 | #print(bid) 550 | j+=1 551 | return ask_price, ask_quantity, bid_price, bid_quantity, place_order_ask_price, place_order_bid_price 552 | #Plot Data 553 | """ 554 | if __name__ == "__main__": 555 | run() 556 | -------------------------------------------------------------------------------- /Historic-Legacy/TriArbBot_Paper_and_Tweet.py: -------------------------------------------------------------------------------- 1 | """ 2 | The Purpose of the PrivateBinance Arbitrage Bot (based on RoibalBot) Python Program is to create an automated trading bot (functionality) on Binance 3 | Utilized Python-Binance ( https://github.com/sammchardy/python-binance ) (NOTE: Use Roibal Fork of Python Binance) 4 | Advanced-Version capable of all exchanges, all coins (using cctx) 5 | 6 | This 'bot' will run a functionality which seeks profitable triangular arbitrage opportunities on Binance 7 | Weekly/Daily/Hourly reports created on profit/loss 8 | 9 | Instructional Youtube Video: https://www.youtube.com/watch?v=8AAN03M8QhA - Additional Videos Available on youtube 10 | 11 | Created 4/14/2018 by Joaquin Roibal 12 | V 0.01 - Updated 4/20/2018 13 | v 0.02 - Updated 5/30/2018 - Converted to Advanced Version: https://github.com/Roibal/Cryptocurrency-Trading-Bots-Python-Beginner-Advance 14 | v 0.03 - Created 6/18/2018 - Binance Arbitrage Bot 15 | v 0.04 - 6/21/2018 - Changed Name to CryptoTriangularArbitrageBinanceBot.py 16 | v 1.00 - 6/24/2018 - Converted to Private_TriArbBot.py for Private Trader Group 17 | v 1.01 - 6/27/2018 - Incorporated Fees & Live Trading Functionality 18 | v 1.02 - 6/27/2018 - Fixed Order Functionality, Order Amounts, Fee Calculation 19 | v 1.03 - 6/27/2018 - Converted to Paper & Tweet format - will collect, save data & tweet every few minutes 20 | 21 | All Rights Reserved 22 | 23 | ATTENTION: BY RUNNING SCRIPT YOU AGREE TO REMIT 1% of PROFITS TO THE FOLLOWING ADDRESS DAILY: 24 | BTC: 1BYrAED4pi5DMKu2qZPv8pwe6rEeuxoCiD 25 | 26 | NOTE: All Subsequent Version of Program must contain this message, unmodified, in it's entirety 27 | Copyright (c) 2018 by Joaquin Roibal 28 | """ 29 | 30 | from binance.client import Client 31 | from binance.enums import * 32 | import time 33 | from datetime import datetime 34 | import matplotlib 35 | from matplotlib import cm 36 | import matplotlib.pyplot as plt 37 | from binance.enums import * 38 | #import pprint 39 | #import win32api 40 | #import save_historical_data_Roibal 41 | import math 42 | from BinanceKeys import BinanceKey1 43 | import pprint 44 | import tweepy 45 | 46 | api_key = BinanceKey1['api_key'] 47 | api_secret = BinanceKey1['api_secret'] 48 | #load twitter instantiating code 49 | #Oauth consumer key/secret and token/secret from twitter application 50 | consumer_key = 51 | consumer_secret = 52 | access_token = 53 | access_token_secret = 54 | 55 | #Authorization for Tweepy format 56 | auth = tweepy.OAuthHandler(consumer_key, consumer_secret) 57 | auth.set_access_token(access_token, access_token_secret) 58 | api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) 59 | 60 | 61 | client = Client(api_key, api_secret) 62 | print(client) 63 | #client.synced('order_market_buy', symbol='BNBBTC', quantity=10) 64 | 65 | def run(): 66 | #set_time_binance() 67 | #Initialize Arbitrage Binance Bot on Infinite Loop 68 | while 1: 69 | initialize_arb() 70 | 71 | 72 | #Perform our Arbitrage Function 73 | 74 | #Data Output (log) in a text file - keep track of start/end time, trades, balance 75 | pass 76 | 77 | def set_time_binance(): 78 | #Code By Khal Q 79 | gt=client.get_server_time() 80 | tt=time.gmtime(int((gt["serverTime"])/1000)) 81 | #win32api.SetSystemTime(tt[0], tt[1],0,tt[2], tt[3], tt[4],tt[5],0) 82 | def initialize_arb(): 83 | 84 | welcome_message = "\n\n---------------------------------------------------------\n\n" 85 | welcome_message+= "Hello and Welcome to the Binance Arbitrage Crypto Trader Bot Python Script\nCreated 2018 by Joaquin Roibal (@BlockchainEng)" 86 | welcome_message+= "A quick 'run-through' will be performed to introduce you to the functionality of this bot\n" 87 | welcome_message+="To learn more visit medium.com/@BlockchainEng or watch introductory Youtube Videos" 88 | welcome_message+="\nCopyright 2018 by Joaquin Roibal\n" 89 | bot_start_time = str(datetime.now()) 90 | welcome_message+= "\nBot Start Time: {}\n\n\n".format(bot_start_time) 91 | print(welcome_message) 92 | #info = client.get_account() 93 | #Clear All Pending Trades 94 | 95 | #print(info) 96 | #welcome_message+=str(info) 97 | time.sleep(5) 98 | #trades = client.get_my_trades(symbol='BNBBTC') 99 | #print(trades) 100 | #data_log_to_file(balance) 101 | 102 | #output to file - create function 103 | data_log_to_file(welcome_message) 104 | time.sleep(5) 105 | try: 106 | status = client.get_system_status() 107 | #print("\nExchange Status: ", status) 108 | 109 | #Account Withdrawal History Info 110 | withdraws = client.get_withdraw_history() 111 | #print("\nClient Withdraw History: ", withdraws) 112 | 113 | #for symbol in list_of_symbols: 114 | #market_depth(symbol) 115 | #Collect all Symbols for Exchange 116 | #Find Arbitrage Opportunities 117 | coin_list = ['BTC', 'ETH', 'USDT', 'BNB', 'THETA', 'NANO'] 118 | balance_list = [] 119 | #for coin in coin_list: 120 | # balance_list.append(client.get_asset_balance(coin)) 121 | print(balance_list) 122 | data_log_to_file(str(balance_list)) 123 | list_of_symbols = ['BNBBTC', 'THETABNB', 'THETABTC'] 124 | list_of_symbols2 = ['BNBBTC', 'NANOBNB', 'NANOBTC'] 125 | list_of_symbols22 = ['BNBBTC', 'CVCBNB', 'CVCBTC'] 126 | list_of_symbols3 = ['BTCUSDT', 'BNBBTC', 'BNBUSDT'] 127 | list_of_symbols4 = ['ETHBTC', 'BNBETH', 'BNBBTC'] 128 | list_of_symbols5 = ['ETHUSDT', 'BNBETH', 'BNBUSDT'] 129 | list_of_arb_sym = [list_of_symbols, list_of_symbols2, list_of_symbols22, list_of_symbols3, list_of_symbols4, list_of_symbols5] 130 | 131 | #Create List of all balance amounts for each coin: 132 | msg1 = "LOADING BALANCES FROM BINANCE" 133 | #Get Binance Wallet Balance - Split into 4 coins evenly 134 | print(msg1) 135 | data_log_to_file(msg1) 136 | list_balance = [] 137 | #for sym in list_of_arb_sym: 138 | #for sym2 in sym: 139 | # orders = client.get_all_orders(symbol=sym2, limit=10) 140 | # list_balance.append(orders) 141 | #data_log_to_file(list_balance) 142 | #pprint(list_balance) 143 | 144 | #info = client.get_symbol_info(sym) 145 | #print(info) 146 | #prices = client.get_all_tickers() 147 | tickers = client.get_orderbook_tickers() 148 | #print(prices) 149 | #print(tickers) 150 | #portfolio = [10, 100, 10000, 500, str(datetime.now())] #Number of: [Bitcoin, Ethereum, USDT, Binance Coin] 151 | #Load Binance Portfolio 152 | #binance_portfolio(coin_list) 153 | #Load Portfolio File 154 | portfolio=[] 155 | msg="Crypto Trading Bot - Arbitrage Market Analysis" 156 | with open('Portfolio.txt') as f1: 157 | read_data = f1.readlines() 158 | for line in read_data: 159 | load_portfolio = line #Load Previous Portfolio 160 | load_portfolio = list(load_portfolio[1:-1].split(',')) 161 | #Load From Binance 162 | #print(load_portfolio) 163 | #time.sleep(5) 164 | #for i in range(0,3): 165 | #portfolio[i] = float(portfolio[i]) #Set Type for first 4 values of Portfolio 166 | i=0 167 | for val in load_portfolio: 168 | #print(val.strip()) 169 | if i == 4: 170 | portfolio.append(str(datetime.now())) 171 | break 172 | portfolio.append(float(val.strip())) 173 | i+=1 174 | portf_msg = "Starting Portfolio (Paper): " + str(portfolio) 175 | #Load Balances for each coin in exchange 176 | #Split BTC into 4 equal amounts, buy all 3 other coins with that amount 177 | print(portf_msg) 178 | portf_file_save(portfolio) 179 | data_log_to_file(portf_msg) 180 | while 1: 181 | #Run Arbitrage Profit Functionality - To Determine Highest Profit Percentage - Cont Loop 182 | calc_profit_list =[] 183 | for arb_market in list_of_arb_sym: 184 | arb_bin, j = arbitrage_bin(arb_market, tickers, portfolio, 1, 1) 185 | calc_profit_list.append(arb_bin) 186 | 187 | for profit1 in calc_profit_list: 188 | data_log_to_file(str(profit1)) 189 | print(calc_profit_list) 190 | exp_profit = 0 #Expected Profit, Set to 0 initially 191 | m = n = 0 #Market Position Market 192 | for exch_market in calc_profit_list: 193 | if exch_market[4]>exp_profit: 194 | exp_profit = exch_market[4] 195 | m = n 196 | n+=1 197 | profit_message = "\nMost Profitable Market: {} \nExpected Profit: {}%".format(list_of_arb_sym[m], exp_profit) 198 | print(profit_message) 199 | msg+= profit_message 200 | data_log_to_file(profit_message) 201 | time.sleep(15) 202 | #Run Arbitrage Function on Highest Profit Percentage Coin for 10 minutes 203 | arb_list_data = [] 204 | arb_start_time = str(datetime.now()) 205 | for i in range(0,45): 206 | #Collect Arbitrage Data Into List format for 5 cycles, 30 second cycles (replaces functionality) 207 | 208 | try: 209 | arb_bin2, j2 = arbitrage_bin(list_of_arb_sym[m], tickers, portfolio, 1, 1, 'No', 'No') 210 | arb_list_data.append(arb_bin2) #'Yes' to place orders 211 | #binance_portfolio(coin_list) 212 | except: 213 | raise 214 | pass 215 | #print(arb_l ist_data) 216 | time.sleep(30) 217 | arb_end_time = str(datetime.now()) 218 | #Visualize Collected Arb List Data with MatPlotLib 219 | #msg+=profit_message 220 | data_log_to_file(msg) #Save to Output the Message to be tweeted 221 | viz_arb_data(arb_list_data, list_of_arb_sym[m], arb_start_time, arb_end_time, 'Yes', msg) #Add 'Yes' for tweet 222 | except: 223 | print("\nFAILURE INITIALIZE\n") 224 | raise 225 | 226 | def data_log_to_file(message): 227 | with open('CryptoTriArbBot_DataLog.txt', 'a+') as f: 228 | f.write(message) 229 | 230 | def portf_file_save(portfolio, filename='Portfolio.txt'): 231 | with open(filename, 'a+') as f: 232 | f.write('\n'+str(portfolio)) 233 | 234 | def arbitrage_bin(list_of_sym, tickers, portfolio, cycle_num=10, cycle_time=30, place_order='No', real_order='No', msg = []): 235 | #Create Triangular Arbitrage Function 236 | arb_message = "Beginning Binance Arbitrage Function Data Collection - Running\n" 237 | print(arb_message) 238 | data_log_to_file(arb_message) 239 | #time.sleep(2) 240 | fee_percentage = 0.05*3 #divided by 100 241 | #Created Arbitrage Functionality for with Python-Binance 242 | for i in range(0,1): #initialize Exchange 243 | #create blacklist of exchanges 244 | 245 | #exchange1 = getattr (ccxt, exch) () 246 | #symbols = tickers.keys() 247 | #print(symbols) 248 | #time.sleep(20) 249 | #Find Pairs to Trade 250 | """ 251 | pairs = [] 252 | for sym in symbols: 253 | for symbol in coins: 254 | if symbol in sym: 255 | pairs.append(sym) 256 | print(pairs) 257 | #From Coin 1 to Coin 2 - ETH/BTC - Bid 258 | #From Coin 2 to Coin 3 - ETH/LTC - Ask 259 | #From Coin 3 to Coin 1 - BTC/LTC - Bid 260 | arb_list = ['ETH/BTC'] #, 'ETH/LTC', 'BTC/LTC'] 261 | #Find 'closed loop' of currency rate pairs 262 | j=0 263 | while 1: 264 | if j == 1: 265 | final = arb_list[0][-3:] + '/' + str(arb_list[1][-3:]) 266 | print(final) 267 | #if final in symbols: 268 | arb_list.append(final) 269 | break 270 | for sym in symbols: 271 | if sym in arb_list: 272 | pass 273 | else: 274 | if j % 2 == 0: 275 | if arb_list[j][0:3] == sym[0:3]: 276 | if arb_list[j] == sym: 277 | pass 278 | else: 279 | arb_list.append(sym) 280 | print(arb_list) 281 | j+=1 282 | break 283 | if j % 2 == 1: 284 | if arb_list[j][-3:] == sym[-3:]: 285 | if arb_list[j] == sym: 286 | pass 287 | else: 288 | arb_list.append(sym) 289 | print(arb_list) 290 | j+=1 291 | break 292 | """ 293 | #time.sleep(.5) 294 | print("List of Arbitrage Symbols:", list_of_sym) 295 | #time.sleep(3) 296 | #Determine Rates for our 3 currency pairs - order book 297 | list_exch_rate_list = [] 298 | if 1: 299 | #Create Visualization of Currency Exchange Rate Value - Over Time 300 | #Determine Cycle number (when data is taken) and time when taken 301 | for k in range(0,cycle_num): 302 | i=0 303 | exch_rate_list = [] 304 | profit_fee_list = [] 305 | data_collect_message1 = "Data Collection Cycle Number: "+str(k) +'\n' 306 | #print(data_collect_message1) 307 | data_log_to_file(data_collect_message1) 308 | for sym in list_of_sym: 309 | currency_pair = "Currency Pair: "+str(sym)+" " 310 | if sym in list_of_sym: 311 | #depth = client.get_(sym) 312 | #print(depth) 313 | """if i == 0: #For first in triangle 314 | depth = client.get_order_book(symbol=sym) 315 | exch_rate_list.append(float(depth['bids'][0][0])) 316 | print(depth['bids'][0][0]) 317 | """ 318 | if i % 2==0: 319 | #exch_rate_list.append(depth['bids'][0][0]) #converted to Binance 320 | depth = client.get_order_book(symbol=sym) 321 | inv1 = depth['asks'][0][0] 322 | exch_rate_list.append(float(inv1)) #Inverse Because of Binance Format 323 | Exch_rate1 = currency_pair+ "Exchange Rate: {}".format(depth['asks'][0][0]) +' ' 324 | print(Exch_rate1) 325 | data_log_to_file(Exch_rate1) 326 | if i == 1: 327 | #exch_rate_list.append(depth['asks'][0][0]) 328 | depth = client.get_order_book(symbol=sym) 329 | inv2 = round(1.0/float(depth['bids'][0][0]),6) 330 | exch_rate_list.append(float(inv2)) #Inverse because Binance Format 331 | Exch_rate2 = currency_pair+"Exchange Rate: {}".format(depth['bids'][0][0])+' ' 332 | print(Exch_rate2) 333 | data_log_to_file(Exch_rate2) 334 | i+=1 335 | else: 336 | exch_rate_list.append(0) 337 | 338 | #exch_rate_list.append(((rateB[-1]-rateA[-1])/rateA[-1])*100) #Expected Profit 339 | exch_rate_list.append(datetime.now()) #changed to Human Readable time 340 | #time.sleep(10) 341 | #Compare to determine if Arbitrage opp exists 342 | rate1 = exch_rate_list[0] 343 | buy_price = "Buy: {}".format(rate1) 344 | print(buy_price) 345 | data_log_to_file(buy_price) 346 | rate2 = float(exch_rate_list[2])*float(exch_rate_list[1]) 347 | sell_price = "Sell: {}".format(rate2) 348 | print(sell_price) 349 | data_log_to_file(sell_price) 350 | if float(rate1)0: 376 | portf_file_save(portfolio2, "Portfolio_fees_strategy1.txt") 377 | portf_file_save(portfolio) 378 | portf_file_save(portfolio2, 'Portfolio_fees.txt') 379 | #If Function is submitted requesting 'Real Order' 380 | if real_order == 'Yes': 381 | if arb_profit>fee_percentage: 382 | real_order_msg = "ENTERING REAL ORDER: " 383 | real_order_msg += "NO FEE PROFIT PERCENTAGE: "+str(arb_profit) 384 | real_order_msg += "FEE PERCENTAGE: "+str(fee_percentage) 385 | real_order_msg += "ARBITRAGING: "+str(list_of_sym) 386 | print(real_order_msg) 387 | msg+= real_order_msg 388 | data_log_to_file(real_order_msg) 389 | #Place 3 orders in succession buying/selling coins for the tri arb 390 | quantity = [0.005, 0.21, 15, 1, 60, 60, 60] #Limit Amounts For Trading 391 | real_order_msg1 = "REAL ORDER BUY (1): " +str(list_of_sym[0]) 392 | port, amt_coin1, amt_coin2, amt_coin3, amt_coin_final = tri_arb_paper(quantity, list_of_sym, exch_rate_list, 'Yes') 393 | coin_amts = [amt_coin1, amt_coin2[-1], amt_coin3[-1], amt_coin_final[-1]] 394 | #Round Coin Amounts of Binance Coin (must be purchased in whole amounts) 395 | for a, sym in enumerate(list_of_sym): 396 | print(sym) 397 | if sym[0:3]=='BNB' or sym[-3:]=='BNB': 398 | coin_amts[a+1] = math.ceil(coin_amts[a+1]) 399 | print(coin_amts[a]) 400 | real_order_msg1 += "Coin Amounts to Purchase: "+str(coin_amts) 401 | print(real_order_msg1) 402 | real_order_start_time = datetime.now() 403 | real_order_msg1+="\nSTART TIME: " + str(real_order_start_time)+"\n\n" 404 | #First Order - Coin 2 from Starting Coin - 405 | price_order_1 = round(float(exch_rate_list[int(0)]),5) 406 | quantity_1 = round(coin_amts[1], 5) 407 | order_1 = client.create_order (symbol=list_of_sym[0], 408 | side=SIDE_BUY, 409 | type=ORDER_TYPE_LIMIT, 410 | quantity=quantity_1, 411 | price=price_order_1, 412 | timeInForce=TIME_IN_FORCE_GTC) 413 | real_order_msg1 += str(order_1) +'\n'+str(quantity_1) 414 | 415 | price_order_2 = round((1/exch_rate_list[1]), 5) 416 | print(price_order_2) 417 | quantity_2 = round(coin_amts[2], 5) 418 | order_2 = client.create_order (symbol=list_of_sym[1], 419 | side=SIDE_BUY, 420 | type=ORDER_TYPE_LIMIT, 421 | quantity=quantity_2, 422 | price=price_order_2, 423 | timeInForce=TIME_IN_FORCE_GTC) 424 | real_order_msg1 += str(order_2)+'\n'+str(quantity_2) 425 | real_order_msg1 += "\n\nREAL ORDER SELL: \n" 426 | price_order_3 = round(float(exch_rate_list[int(2)]),5) 427 | quantity_3 = round(coin_amts[3], 5) 428 | order_3 = client.create_order (symbol=list_of_sym[2], 429 | side=SIDE_SELL, 430 | type=ORDER_TYPE_LIMIT, 431 | quantity=quantity_3, 432 | price=price_order_3, 433 | timeInForce=TIME_IN_FORCE_GTC) 434 | real_order_msg1+= str(order_3)+'\n'+str(quantity_3) 435 | real_order_stop_time = datetime.now() 436 | real_order_msg1+= str(real_order_stop_time) 437 | portf_file_save(real_order_msg, 'Real_Order_Messages_Log.txt') 438 | real_order_msg_prices = [price_order_1, price_order_2, price_order_3] 439 | real_order_quantity = [quantity_1, quantity_2, quantity_3] 440 | real_order_msg_prices+=real_order_quantity 441 | real_order_msg_prices.append(datetime.now()) 442 | real_order_msg1+= real_order_msg_prices 443 | print(real_order_msg1) 444 | list_of_orders = [order_1, order_2, order_3] 445 | #plc_order_msg = "Placing Order: "+ str(order) 446 | for plc_order_msg in list_of_orders: 447 | portf_file_save(plc_order_msg, 'PlaceOrderLog.txt') 448 | for prices in real_order_msg_prices: 449 | portf_file_save(real_order_msg_prices, 'RealOrderPrices.txt') 450 | data_log_to_file(real_order_msg1) 451 | #Call function that will paper-trade with portfolio 452 | #portfolio = list(portfolio) 453 | portfolio = tri_arb_paper(portfolio, list_of_sym, exch_rate_list) 454 | portf_file_save(portfolio) 455 | else: 456 | arb_2_msg = "No Arbitrage Possibility" 457 | print(arb_2_msg) 458 | data_log_to_file(arb_2_msg) 459 | #Add 0 for profit to list 460 | exch_rate_list.append(0) 461 | exch_msg = "Exchange Rate List: " +str(exch_rate_list)+'\n' 462 | #for exch_list in exch_rate_list: 463 | #print(exch_msg) 464 | data_log_to_file(exch_msg) 465 | #Format data (list) into List format (list of lists) 466 | #list_exch_rate_list.append(exch_rate_list) 467 | time.sleep(cycle_time) 468 | #print(list_exch_rate_list) 469 | print('\nARBITRAGE FUNCTIONALITY SUCCESSFUL - Data of Exchange Rates Collected\n') 470 | return exch_rate_list, msg 471 | 472 | def tri_arb_paper(portfolio1, sym_list, list_exch_rates, fees='No', fee=0.0005): 473 | #Determine Which Coin Starting With 474 | tri_arb_paper_msg = "\nSTARTING TRI ARB PAPER TRADING FUNCTION\n" 475 | print(tri_arb_paper_msg) 476 | #print(portfolio1) 477 | #time.sleep(10) 478 | data_log_to_file(tri_arb_paper_msg) 479 | if sym_list[0][-3:]=='BTC': 480 | portf_pos = 0 481 | elif sym_list[0][-3:]=='ETH': 482 | portf_pos = 1 483 | elif sym_list[0][-3:]=='SDT': 484 | portf_pos = 2 485 | elif sym_list[0][-3:]=='BNB': 486 | portf_pos = 3 487 | elif sym_list[0][-3:]=='ANO': 488 | portf_pos = 4 489 | elif sym_list[0][-3:]=='ETA': 490 | portf_pos = 5 491 | elif sym_list[0][-3:]=='CVC': 492 | portf_pos = 6 493 | if fees == 'Yes': 494 | start_amount = float(portfolio1[portf_pos]) 495 | amt_coin2 = start_amount / float(list_exch_rates[0]) 496 | amt_coin2_no_fee = amt_coin2 497 | amt_coin2_fee = amt_coin2*fee 498 | amt_coin2_adj = amt_coin2*(1-fee) 499 | amt_coin3 = amt_coin2_adj * float(list_exch_rates[1]) 500 | amt_coin3_no_fee = amt_coin2_no_fee*float(list_exch_rates[1]) 501 | amt_coin3_fee = amt_coin3 * fee 502 | amt_coin3_adj = amt_coin3*(1-fee) 503 | final_amount = amt_coin3_adj * float(list_exch_rates[2]) 504 | final_amount_no_fee = amt_coin3_no_fee * float(list_exch_rates[2]) 505 | final_amount_fee = final_amount *fee 506 | final_amount_adj = final_amount *(1-fee) 507 | tri_arb_paper_msg = "Starting Amount: "+str(sym_list[0][-3:])+" "+str(start_amount)+'\n' 508 | #Buy Currency 2 with Currency 1 509 | tri_arb_paper_msg += "\nAmount Coin 2: "+str(sym_list[0][0:3])+" "+str(amt_coin2)+'\n' 510 | tri_arb_paper_msg += "\nAmount Coin 2 (no fee): "+str(sym_list[0][0:3])+" "+str(amt_coin2_no_fee)+'\n' 511 | tri_arb_paper_msg += "\nAmount Coin 2 Fee: "+str(sym_list[0][0:3])+" "+str(amt_coin2_fee)+'\n' 512 | tri_arb_paper_msg += "\nAmount Coin 2 Adjusted: "+str(sym_list[0][0:3])+" "+str(amt_coin2_adj)+'\n' 513 | #Buy Currency 3 with Currency 2 514 | tri_arb_paper_msg += "\nAmount Coin 3: "+str(sym_list[2][0:3])+" "+str(amt_coin3) +'\n' 515 | tri_arb_paper_msg += "\nAmount Coin 3 (no fee): "+str(sym_list[2][0:3])+" "+str(amt_coin3_no_fee) +'\n' 516 | tri_arb_paper_msg += "\nAmount Coin 3 Fee: "+str(sym_list[2][0:3])+" "+str(amt_coin3_fee)+'\n' 517 | tri_arb_paper_msg += "\nAmount Coin 3 Adjusted: "+str(sym_list[2][0:3])+" "+str(amt_coin3_adj)+'\n' 518 | #Buy Currency 1 with Currency 3 519 | tri_arb_paper_msg += "\nFinal Amount: "+str(sym_list[0][-3:])+" "+str(final_amount)+'\n' 520 | tri_arb_paper_msg += "\nFinal Amount (No Fee): "+str(sym_list[0][-3:])+" "+str(final_amount_no_fee)+'\n' 521 | tri_arb_paper_msg += "\nFinal Amount Fee: "+str(sym_list[0][-3:])+" "+str(final_amount_fee)+'\n' 522 | tri_arb_paper_msg += "\nFinal Amount Adjusted: "+str(sym_list[0][-3:])+" "+str(final_amount_adj)+'\n' 523 | #Create Log of 'Volume' and Transfer 524 | #Volume(Total Paid), Fee, Final Amount 525 | coin2_fee_amounts = [amt_coin2, amt_coin2_no_fee, amt_coin2_fee, amt_coin2_adj] 526 | coin3_fee_amounts = [amt_coin3, amt_coin3_no_fee, amt_coin3_fee, amt_coin3_adj] 527 | final_coin_fee_amounts = [final_amount, final_amount_no_fee, final_amount_fee, final_amount_adj] 528 | list_of_fees = [coin2_fee_amounts, coin3_fee_amounts, final_coin_fee_amounts] 529 | print(tri_arb_paper_msg) 530 | print(list_of_fees) 531 | data_log_to_file(str(list_of_fees)) 532 | for fee in list_of_fees: 533 | portf_file_save(fee, 'list_fees_paid.txt') 534 | data_log_to_file(tri_arb_paper_msg) 535 | portfolio1[portf_pos] = final_amount_adj 536 | portfolio1[-1] = str(datetime.now()) 537 | if fees == 'No': 538 | start_amount = float(portfolio1[portf_pos]) 539 | coin2_fee_amounts = coin3_fee_amounts = final_coin_fee_amounts = [0, 0, 0, 0] #Blank List for these values if Fees = 'No' 540 | amt_coin2 = start_amount / float(list_exch_rates[0]) 541 | amt_coin3 = amt_coin2 * float(list_exch_rates[1]) 542 | final_amount = amt_coin3 * float(list_exch_rates[2]) 543 | tri_arb_paper_msg = "Starting Amount: "+str(sym_list[0][-3:])+" "+str(start_amount)+'\n' 544 | #Buy Currency 2 with Currency 1 545 | tri_arb_paper_msg += "Amount Coin 2: "+str(sym_list[0][0:3])+" "+str(amt_coin2)+'\n' 546 | #Buy Currency 3 with Currency 2 547 | tri_arb_paper_msg += "Amount Coin 3: "+str(sym_list[2][0:3])+" "+str(amt_coin3) +'\n' 548 | #Buy Currency 1 with Currency 3 549 | tri_arb_paper_msg += "Final Amount: "+str(sym_list[0][-3:])+" "+str(final_amount)+'\n' 550 | print(tri_arb_paper_msg) 551 | data_log_to_file(tri_arb_paper_msg) 552 | portfolio1[portf_pos] = final_amount 553 | portfolio1[-1] = str(datetime.now()) 554 | 555 | return portfolio1 , start_amount, coin2_fee_amounts, coin3_fee_amounts, final_coin_fee_amounts 556 | 557 | """ 558 | start_amount = float(portfolio1[portf_pos]) 559 | amt_coin2 = start_amount / float(list_exch_rates[0]) 560 | amt_coin3 = amt_coin2 * float(list_exch_rates[1]) 561 | final_amount = amt_coin3 * float(list_exch_rates[2]) 562 | tri_arb_paper_msg = "Starting Amount: "+str(sym_list[0][-3:])+" "+str(start_amount)+' ' 563 | #Buy Currency 2 with Currency 1 564 | tri_arb_paper_msg += "Amount Coin 2: "+str(sym_list[0][0:3])+" "+str(amt_coin2)+' ' 565 | #Buy Currency 3 with Currency 2 566 | tri_arb_paper_msg += "Amount Coin 3: "+str(sym_list[2][0:3])+" "+str(amt_coin3) +' ' 567 | #Buy Currency 1 with Currency 3 568 | tri_arb_paper_msg += "Final Amount: "+str(sym_list[0][-3:])+" "+str(final_amount)+' ' 569 | print(tri_arb_paper_msg) 570 | data_log_to_file(tri_arb_paper_msg) 571 | portfolio1[portf_pos] = final_amount 572 | portfolio1[-1] = str(datetime.now()) 573 | return portfolio1 574 | """ 575 | 576 | def viz_arb_data(list_exch_rate_list, arb_market, start_time, end_time, Tweet_message='No', msg = []): 577 | viz_msg = "\nARBITRAGE VIZ FUNCTIONALITY\n" 578 | print(viz_msg) 579 | #msg+=viz_msg 580 | data_log_to_file(viz_msg) 581 | #Visualize with Matplotlib 582 | #use matplotlib to plot data 583 | #Create list from Lists for matplotlib format 584 | rateA = [] #Original Exchange Rate 585 | rateB = [] #Calculated/Arbitrage Exchange Rate 586 | rateB_fee = [] #Include Transaction Fee 587 | price1 = [] #List for Price of Token (Trade) 1 588 | price2 = [] #List for price of Token (Trade) 2 589 | time_list = [] #time of data collection 590 | profit_list = [] #Record % profit 591 | for rate in list_exch_rate_list: 592 | rateA.append(rate[0]) 593 | rateB1 = round(float(rate[1])*float(rate[2]),6) 594 | rateB.append(rateB1) #Multiplied together because of Binance Format 595 | #rateB_fee.append((rate[1]/rate[2])*(1-fee_percentage)*(1-fee_percentage)) 596 | price1.append(rate[1]) 597 | price2.append(rate[2]) 598 | profit_list.append(rate[4]) 599 | time_list.append(rate[3]) 600 | viz_msg2 = "Rate A: {} \n Rate B: {} \n Projected Profit (%): {} ".format(rateA, rateB, profit_list) #rateB_fee)) 601 | print(viz_msg2) 602 | data_log_to_file(viz_msg2) 603 | 604 | #from https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot 605 | #Extended 3 axis functionality - https://matplotlib.org/gallery/ticks_and_spines/multiple_yaxis_with_spines.html#sphx-glr-gallery-ticks-and-spines-multiple-yaxis-with-spines-py 606 | #fig, ax = plt.subplots() 607 | fig, host = plt.subplots() 608 | fig.subplots_adjust(right=0.75) 609 | 610 | par1 = host.twinx() 611 | par2 = host.twinx() 612 | par2.spines["right"].set_position(("axes", 1.2)) 613 | make_patch_spines_invisible(par2) 614 | par2.spines["right"].set_visible(True) 615 | #Graph Rate & Calculated Rate on Left Hand Side 616 | p1, = host.plot(time_list, rateA, "k", label = "{}".format(arb_market[0])) 617 | p1, = host.plot(time_list, rateB, "k+", label = "{} * {}".format(arb_market[1], arb_market[2])) 618 | #p1, = host.plot(time_list, rateB_fee, 'k+', label = "{} / {} - with Fee".format(arb_list[1], arb_list[2])) 619 | #Graph Exchange Rate (Originals) 620 | p2, = par1.plot(time_list, price1, "b-", label="Price - {}".format(arb_market[1])) 621 | p3, = par2.plot(time_list, price2, "g-", label="Price - {}".format(arb_market[2])) 622 | #show our graph - with labels 623 | host.set_xlabel("Time") 624 | host.set(title='Triangular Arbitrage - Exchange: {}\nStart Time: {} End Time: {}\n' 625 | 'Copyright (c) 2018 @BlockchainEng'.format('Binance', start_time, end_time)) 626 | host.set_ylabel("Exchange Rate") 627 | par1.set_ylabel("Price - {}".format(arb_market[1])) 628 | par2.set_ylabel("Price - {}".format(arb_market[2])) 629 | host.yaxis.label.set_color(p1.get_color()) 630 | tkw = dict(size=4, width=1.5) 631 | host.tick_params(axis='y', colors=p1.get_color(), **tkw) 632 | par1.tick_params(axis='y', colors=p2.get_color(), **tkw) 633 | par2.tick_params(axis='y', colors=p3.get_color(), **tkw) 634 | host.tick_params(axis='x', **tkw) 635 | 636 | lines = [p1, p2, p3] 637 | host.legend(lines, [l.get_label() for l in lines]) #show Legend 638 | fname = "Binance_Test.png" #+"-"+str(arb_market[0])+str(arb_market[1])+str(arb_market[2])+".png" 639 | #Future: Include Start/End Time 640 | plt.savefig(fname) #Changes to make - Format 641 | """, dpi=None, facecolor='w', edgecolor='w', 642 | orientation='portrait', papertype=None, format=None, 643 | transparent=False, bbox_inches=None, pad_inches=0.1, 644 | frameon=None)""" 645 | print_figure_message = "Data Collected Figure Printed & Saved - " + str(fname) 646 | print(print_figure_message) 647 | data_log_to_file(print_figure_message) 648 | #plt.show() 649 | #Add Functionality that will tweet message with graph as well. 650 | if Tweet_message == 'Yes': 651 | #msg+=viz_msg2 652 | msg+= "\nStart Time: "+str(start_time)+ " End Time: " +str(end_time) 653 | msg+="\n\nvia @BlockchainEng & @CryptoTrade_Bot \n\n #Crypto #BTC" 654 | print(msg) #Tweet this message then upload file 655 | #Tweet msg and Upload the Graph of last time period directly to twitter 656 | print("TWITTER PREVIEW: ", msg) 657 | try: 658 | api.update_with_media(fname, status=msg) 659 | except: 660 | data_log_to_file('ERROR: TWITTER ERROR') 661 | pass 662 | data_log_to_file("TWEET MESSAGE: " +str(msg)) 663 | #Upload File (Latest Visualization: 'fname') 664 | 665 | 666 | def make_patch_spines_invisible(ax): 667 | ax.set_frame_on(True) 668 | ax.patch.set_visible(False) 669 | for sp in ax.spines.values(): 670 | sp.set_visible(False) 671 | 672 | 673 | """ 674 | def market_depth(sym, num_entries=20): 675 | #Get market depth 676 | #Retrieve and format market depth (order book) including time-stamp 677 | i=0 #Used as a counter for number of entries 678 | #print("Order Book: ", convert_time_binance(client.get_server_time())) 679 | depth = client.get_order_book(symbol=sym) 680 | print(depth) 681 | print(depth['asks'][0]) 682 | ask_tot=0.0 683 | ask_price =[] 684 | ask_quantity = [] 685 | bid_price = [] 686 | bid_quantity = [] 687 | bid_tot = 0.0 688 | place_order_ask_price = 0 689 | place_order_bid_price = 0 690 | max_order_ask = 0 691 | max_order_bid = 0 692 | print("\n", sym, "\nDepth ASKS:\n") 693 | print("Price Amount") 694 | for ask in depth['asks']: 695 | if ifloat(max_order_ask): 697 | #Determine Price to place ask order based on highest volume 698 | max_order_ask=ask[1] 699 | place_order_ask_price=round(float(ask[0]),5)-0.0001 700 | #ask_list.append([ask[0], ask[1]]) 701 | ask_price.append(float(ask[0])) 702 | ask_tot+=float(ask[1]) 703 | ask_quantity.append(ask_tot) 704 | #print(ask) 705 | i+=1 706 | j=0 #Secondary Counter for Bids 707 | print("\n", sym, "\nDepth BIDS:\n") 708 | print("Price Amount") 709 | for bid in depth['bids']: 710 | if jfloat(max_order_bid): 712 | #Determine Price to place ask order based on highest volume 713 | max_order_bid=bid[1] 714 | place_order_bid_price=round(float(bid[0]),5)+0.0001 715 | bid_price.append(float(bid[0])) 716 | bid_tot += float(bid[1]) 717 | bid_quantity.append(bid_tot) 718 | #print(bid) 719 | j+=1 720 | return ask_price, ask_quantity, bid_price, bid_quantity, place_order_ask_price, place_order_bid_price 721 | #Plot Data 722 | """ 723 | if __name__ == "__main__": 724 | run() 725 | --------------------------------------------------------------------------------