diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a54843e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andrei + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..929d4a2 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# binance-trading-bot-new-coins +This Binance trading bot detects new coins as soon as they are listed on the Binance exchange and automatically places sell and buy orders. +It comes with trailing stop loss and other features. + +This open source crypto trading bot should able able to quickly detect new coins listings on Binance and quickly ride the price spike. +It comes with a live and test mode so naturally, use at your own risk. + +for a step-by-step guide on how to set it up and configure please see the guide here: [Binance new coin trading bot guide](https://www.cryptomaton.org/2021/08/15/coding-a-binance-trading-bot-that-detects-new-coins-the-moment-they-are-listed/) diff --git a/main.py b/main.py index cd2898a..f424318 100644 --- a/main.py +++ b/main.py @@ -54,139 +54,142 @@ def main(): all_coins = get_all_coins() while True: + try: - # check if the order file exists and load the current orders - # basically the sell block and update TP and SL logic - if os.path.isfile('order.json'): - order = load_order('order.json') + # check if the order file exists and load the current orders + # basically the sell block and update TP and SL logic + if os.path.isfile('order.json'): + order = load_order('order.json') - for coin in list(order): + for coin in list(order): - # store some necesarry trade info for a sell - stored_price = float(order[coin]['price']) - coin_tp = order[coin]['tp'] - coin_sl = order[coin]['sl'] - volume = order[coin]['volume'] + # store some necesarry trade info for a sell + stored_price = float(order[coin]['price']) + coin_tp = order[coin]['tp'] + coin_sl = order[coin]['sl'] + volume = order[coin]['volume'] + symbol = coin.split(pairing)[0] - last_price = get_price(coin, pairing) - # update stop loss and take profit values if threshold is reached - if float(last_price) > stored_price + (stored_price*coin_tp /100) and enable_tsl: - # increase as absolute value for TP - new_tp = float(last_price) + (float(last_price)*ttp /100) - # convert back into % difference from when the coin was bought - new_tp = float( (new_tp - stored_price) / stored_price*100) + last_price = get_price(symbol, pairing) - # same deal as above, only applied to trailing SL - new_sl = float(last_price) - (float(last_price)*tsl /100) - new_sl = float((new_sl - stored_price) / stored_price*100) + # update stop loss and take profit values if threshold is reached + if float(last_price) > stored_price + (stored_price*coin_tp /100) and enable_tsl: + # increase as absolute value for TP + new_tp = float(last_price) + (float(last_price)*ttp /100) + # convert back into % difference from when the coin was bought + new_tp = float( (new_tp - stored_price) / stored_price*100) - # new values to be added to the json file - order[coin]['tp'] = new_tp - order[coin]['sl'] = new_sl - store_order('order.json', order) + # same deal as above, only applied to trailing SL + new_sl = float(last_price) - (float(last_price)*tsl /100) + new_sl = float((new_sl - stored_price) / stored_price*100) - print(f'updated tp: {round(new_tp, 3)} and sl: {round(new_sl, 3)}') + # new values to be added to the json file + order[coin]['tp'] = new_tp + order[coin]['sl'] = new_sl + store_order('order.json', order) - # close trade if tsl is reached or trail option is not enabled - elif float(last_price) < stored_price - (stored_price*sl /100) or float(last_price) > stored_price + (stored_price*tp /100) and not enable_tsl: + print(f'updated tp: {round(new_tp, 3)} and sl: {round(new_sl, 3)}') - try: + # close trade if tsl is reached or trail option is not enabled + elif float(last_price) < stored_price - (stored_price*sl /100) or float(last_price) > stored_price + (stored_price*tp /100) and not enable_tsl: - # sell for real if test mode is set to false - if not test_mode: - sell = create_order(coin+pairing, coin['volume'], 'SELL') + try: + # sell for real if test mode is set to false + if not test_mode: + sell = create_order(coin+pairing, coin['volume'], 'SELL') - print(f"sold {coin} at {(float(last_price) - stored_price) / float(stored_price)*100}") - # remove order from json file - order.pop(coin) - store_order('order.json', order) + print(f"sold {coin} at {(float(last_price) - stored_price) / float(stored_price)*100}") - except Exception as e: - print(e) + # remove order from json file + order.pop(coin) + store_order('order.json', order) - # store sold trades data - else: - if os.path.isfile('sold.json'): - sold_coins = load_order('sold.json') + except Exception as e: + print(e) + # store sold trades data else: - sold_coins = {} + if os.path.isfile('sold.json'): + sold_coins = load_order('sold.json') + + else: + sold_coins = {} + + if not test_mode: + sold_coins[coin] = sell + store_order('sold.json', sold_coins) + else: + sold_coins[coin] = { + 'symbol':coin+pairing, + 'price':last_price, + 'volume':volume, + 'time':datetime.timestamp(datetime.now()), + 'profit': float(last_price) - stored_price, + 'relative_profit': round((float(last_price) - stored_price) / stored_price*100, 3) + } + + store_order('sold.json', sold_coins) + + else: + order = {} + + # store new coins and rechecked coins list here + new_coins, all_coins_recheck = get_new_coins(all_coins) + + # the buy block and logic pass + if len(new_coins) > 0: + + all_coins = all_coins_recheck + print(f'New coins detected: {new_coins}') + + for coin in new_coins: + + # buy if the coin hasn't already been bought + if coin['symbol'] not in order and pairing in coin['symbol']: + symbol_only = coin['symbol'].split(pairing)[0] + print(f"Preparing to buy {coin['symbol']}") + + price = get_price(symbol_only, pairing) + volume = convert_volume(coin['symbol'], qty, price) + + try: + # Run a test trade if true + if config['TRADE_OPTIONS']['TEST']: + order[coin['symbol']] = { + 'symbol':symbol_only+pairing, + 'price':price, + 'volume':volume, + 'time':datetime.timestamp(datetime.now()), + 'tp': tp, + 'sl': sl + } + + print('PLACING TEST ORDER') + + # place a live order if False + else: + order[coin['symbol']] = create_order(symbol_only+pairing, volume, 'BUY') + order[coin['symbol']]['tp'] = tp + order[coin['symbol']]['sl'] = sl + + except Exception as e: + print(e) - if not test_mode: - sold_coins[coin] = sell - store_order('sold.json', sold_coins) - else: - sold_coins[coin] = { - 'symbol':coin+pairing, - 'price':last_price, - 'volume':volume, - 'time':datetime.timestamp(datetime.now()), - 'profit': float(last_price) - stored_price, - 'relative_profit': round((float(last_price) - stored_price) / stored_price*100, 3) - } - - store_order('sold.json', sold_coins) - - else: - order = {} - - # store new coins and rechecked coins list here - new_coins, all_coins_recheck = get_new_coins(all_coins) - - # the buy block and logic pass - if len(new_coins) > 0: - - all_coins = all_coins_recheck - print(f'New coins detected: {new_coins}') - - for coin in new_coins: - - # buy if the coin hasn't already been bought - if coin['symbol'] not in order and pairing in coin: - symbol_only = coin['symbol'].split(pairing)[0] - print(f"Preparing to buy {coin['symbol']}") - - price = get_price(symbol_only, pairing) - volume = convert_volume(coin['symbol']+pairing, qty, price) - - try: - # Run a test trade if true - if config['TRADE_OPTIONS']['TEST']: - order[coin['symbol']] = { - 'symbol':symbol_only+pairing, - 'price':price, - 'volume':volume, - 'time':datetime.timestamp(datetime.now()), - 'tp': tp, - 'sl': sl - } - - print('PLACING TEST ORDER') - - # place a live order if False else: - order[coin['symbol']] = create_order(symbol_only+pairing, volume, 'BUY') - order[coin['symbol']]['tp'] = tp - order[coin['symbol']]['sl'] = sl - - except Exception as e: - print(e) + print(f"Order created with {volume} on {coin['symbol']}") + store_order('order.json', order) else: - print(f"Order created with {volume} on {coin['symbol']}") - - store_order('order.json', order) - else: - print(f"New coin['symbol'] detected, but {coin['symbol']} is currently in portfolio") + print(f"New coin detected, but {coin['symbol']} is currently in portfolio, or {pairing} does not match") - else: - pass - #print(f"No new coins detected, checking again in {frequency} minute(s)..") + else: + pass - time.sleep(60*frequency) + except Exception as e: + print(e) if __name__ == '__main__': diff --git a/trade_client.py b/trade_client.py index 7dc5b85..45c5e55 100644 --- a/trade_client.py +++ b/trade_client.py @@ -18,8 +18,11 @@ def convert_volume(coin, quantity, last_price): lot_size[coin] = 0 except: + print("Ran except block for lot size") + lot_size = {coin:0} pass + print(lot_size[coin]) # calculate the volume in coin from QUANTITY in USDT (default) volume = float(quantity / float(last_price)) @@ -37,13 +40,13 @@ def convert_volume(coin, quantity, last_price): return volume -def create_order(coin, quantity, type): +def create_order(coin, amount, action): """ Creates simple buy order and returns the order """ return client.create_order( symbol = coin, - side = type, + side = action, type = 'MARKET', - quantity = quantity + quantity = amount )