├── bot.py └── test.jpg /bot.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | import hmac 5 | import hashlib 6 | import twitter 7 | import os 8 | import pytesseract 9 | import urllib, cStringIO 10 | 11 | try: 12 | import Image 13 | except ImportError: 14 | from PIL import Image 15 | try: 16 | from urllib import urlencode 17 | except ImportError: 18 | from urllib.parse import urlencode 19 | 20 | from pprint import pprint 21 | from datetime import datetime, timedelta 22 | 23 | # Location of tesseract executable 24 | pytesseract.pytesseract.tesseract_cmd = '/usr/local/bin/tesseract' 25 | 26 | # Twitter API Keys 27 | CONSUMER_KEY = os.environ.get('TWITTER_CONSUMER_KEY') 28 | CONSUMER_SECRET = os.environ.get('TWITTER_CONSUMER_SECRET') 29 | ACCESS_KEY = os.environ.get('TWITTER_ACCESS_KEY') 30 | ACCESS_SECRET = os.environ.get('TWITTER_ACCESS_SECRET') 31 | 32 | # Bittrex API Keys 33 | BIT_KEY = os.environ.get('BITTREX_KEY') 34 | BIT_SECRET = os.environ.get('BITTREX_SECRET') 35 | 36 | # Constants 37 | AVAILABLE_BTC = .01 38 | PROFIT_MARGIN = 1.2 39 | STOP_LOSS_PERCENT = .95 40 | 41 | api = twitter.Api(consumer_key=CONSUMER_KEY, 42 | consumer_secret=CONSUMER_SECRET, 43 | access_token_key=ACCESS_KEY, 44 | access_token_secret=ACCESS_SECRET) 45 | 46 | def get_bittrex_markets(): 47 | """ Returns all trading pairs on bittrex """ 48 | r = requests.get('https://bittrex.com/api/v1.1/public/getmarkets') 49 | return r.json()['result'] 50 | 51 | def get_ticker_price(pairName): 52 | """ Returns current trading price of a pair on bittrex """ 53 | r = requests.get('https://bittrex.com/api/v1.1/public/getticker?market=' + pairName) 54 | return r.json()['result']['Last'] 55 | 56 | def market_order(trade_type='sell',market=None, order_type='MARKET', quantity=None, rate=0, time_in_effect='FILL_OR_KILL', 57 | condition_type='NONE', target=0): 58 | """ 59 | Enter a buy order into the book 60 | Endpoint v2.0: /key/market/tradebuy 61 | :param market (str): String literal for the market (ex: BTC-LTC) 62 | :param order_type (str): ORDERTYPE_LIMIT = 'LIMIT' or ORDERTYPE_MARKET = 'MARKET' 63 | :param quantity (float): The amount to purchase 64 | """ 65 | options = { 66 | 'marketname': market, 67 | 'ordertype': order_type, 68 | 'quantity': quantity, 69 | 'rate': rate, 70 | 'timeInEffect': time_in_effect, 71 | 'conditiontype': condition_type, 72 | 'target': target 73 | } 74 | 75 | request_url = 'https://bittrex.com/api/v2.0/key/market/trade{0}?'.format(trade_type) 76 | 77 | # unique always increasing integer 78 | nonce = str(int(time.time() * 1000)) 79 | 80 | request_url = "{0}apikey={1}&nonce={2}&".format(request_url, BIT_KEY, nonce) 81 | request_url += urlencode(options) 82 | 83 | apisign = hmac.new(BIT_SECRET.encode(), 84 | request_url.encode(), 85 | hashlib.sha512).hexdigest() 86 | 87 | return requests.get( 88 | request_url, 89 | headers={"apisign": apisign} 90 | ).json() 91 | 92 | def strategy(coin): 93 | """ 94 | Current Strategy: Buy immediately for pump 95 | Wait until price reaches target price or break even for stop loss 96 | """ 97 | # get current price 98 | curr_price = get_ticker_price(coin['pairName']) 99 | 100 | # set constants 101 | QUANTITY = AVAILABLE_BTC/curr_price 102 | STOP_LOSS_PRICE = curr_price * STOP_LOSS_PERCENT 103 | EXIT_PRICE = curr_price * PROFIT_MARGIN 104 | 105 | # logging 106 | print("AVAILABLE BTC: " + str(AVAILABLE_BTC)) 107 | print("STOP LOSS PRICE: " + str(STOP_LOSS_PRICE)) 108 | print("EXIT PRICE: " + str(EXIT_PRICE) + '\n') 109 | print("BUYING: " + str(QUANTITY) + " " + coin['fullName'] + " at " + str(curr_price) + " BTC") 110 | 111 | market_order(trade_type='buy', 112 | market=coin['pairName'], 113 | quantity=QUANTITY) 114 | 115 | # while price is in holding range 116 | while STOP_LOSS_PRICE < get_ticker_price(coin['pairName']) < EXIT_PRICE: 117 | time.sleep(1) 118 | 119 | # execute market sell 120 | curr_price = get_ticker_price(coin['pairName']) 121 | print("SELLING: " + str(AVAILABLE_BTC/last_price) + " " + coin['fullName'] + " at " + str(curr_price) + " BTC") 122 | 123 | market_order(trade_type='sell', 124 | market=coin['pairName'], 125 | quantity=QUANTITY) 126 | 127 | def listen_tweet(user='officialmcafee'): 128 | """ Listens in on McAfee's twitter feed and returns next tweet text """ 129 | for line in api.GetUserStream(withuser=user): 130 | # if image contained in tweet 131 | if line.get('entities') and line.get('entities').get('media'): 132 | image_url = line['entities']['media'][0]['media_url'] 133 | file = cStringIO.StringIO(urllib.urlopen(image_url).read()) 134 | img = Image.open(file) 135 | 136 | # return text in image tweet 137 | return pytesseract.image_to_string(img) 138 | 139 | # if regular tweet with text 140 | elif line.get('user') and line['user']['screen_name'] == user and line['text'][0] != '@': 141 | return line['text'] 142 | 143 | def preprocess(tweet_text): 144 | """ Given a string representing tweet text, returns tokenized list of lowercase strings """ 145 | return tweet_text.lower().split() 146 | 147 | if __name__ == '__main__': 148 | tokenized_tweet = preprocess(listen_tweet()) 149 | 150 | # list of currencies available on bittrex as dictionaries 151 | currencies = [] 152 | bittrex_markets = get_bittrex_markets() 153 | 154 | for market in bittrex_markets: 155 | # if the pair trades in btc 156 | if 'btc' in market['MarketName'].lower(): 157 | currencies.append({ 158 | 'fullName':market['MarketCurrencyLong'], 159 | 'ticker':market['MarketCurrency'], 160 | 'pairName':market['MarketName'] 161 | }) 162 | 163 | # list of currencies mcafee mentioned 164 | to_buy = [] 165 | for currency in currencies: 166 | if currency['fullName'].lower() in tokenized_tweet or currency['ticker'].lower() in tokenized_tweet: 167 | to_buy.append(currency) 168 | 169 | # if this isnt a decisive choice of what to buy 170 | if len(to_buy) != 1: 171 | print("ERROR: Currencies not available on Bittrex or more than one currency mentioned...") 172 | print("Currencies: " + ','.join(to_buy)) 173 | exit(1) 174 | 175 | # begin pump and dump given coin 176 | strategy(to_buy[0]) 177 | exit(0) 178 | -------------------------------------------------------------------------------- /test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ryanlpeterman/pump-and-dump-bot/cc03f1d7e5bce48c6a476f26e8d0cf66315c4680/test.jpg --------------------------------------------------------------------------------