Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ _Now when your alerts fire off they should go strait to your server and get proc
|type | Market or Limit |
|order_mode| Both(Stop Loss & Take Profit Orders Used), Profit ( Omly Take Profit Orders), Stop (Only Stop Loss orders)|
|qty| amount of base currency to buy |
|qty_percent| optional percent of available quote-currency balance to use instead of qty |
|quote_coin / quote_currency| optional quote balance currency for qty_percent, for example USDT |
|price| ticker in quote currency |
|close_position| True or False |
|cancel_orders|True or False |
Expand Down
62 changes: 40 additions & 22 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ def validate_binance_api_key(exchange):
with open('config.json') as config_file:
config = json.load(config_file)

def calculate_percent_qty(balance, price, percent):
return (float(balance) * (float(percent) / 100)) / float(price)

def get_bybit_wallet_balance(session, coin):
wallet_balance = session.get_wallet_balance(coin=coin)
result = wallet_balance.get('result', {})
coin_balance = result.get(coin, result)
return coin_balance.get('available_balance') or coin_balance.get('wallet_balance')

def get_bybit_order_qty(session, data, price):
if 'qty_percent' not in data:
return data['qty']

quote_coin = data.get('quote_coin') or data['symbol'][-4:]
balance = get_bybit_wallet_balance(session, quote_coin)
return calculate_percent_qty(balance, price, data['qty_percent'])

###############################################################################
#
# This Section is for Exchange Validation
Expand Down Expand Up @@ -114,11 +131,12 @@ def webhook():
else:
price = 0

current_price = session.latest_information_for_symbol(symbol=data['symbol'])['result'][0]['last_price']
qty = get_bybit_order_qty(session, data, current_price)

if data['order_mode'] == 'Both':
take_profit_percent = float(data['take_profit_percent'])/100
stop_loss_percent = float(data['stop_loss_percent'])/100
current_price = session.latest_information_for_symbol(symbol=data['symbol'])['result'][0]['last_price']
if data['side'] == 'Buy':
take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent), 2)
stop_loss_price = round(float(current_price) - (float(current_price) * stop_loss_percent), 2)
Expand All @@ -130,37 +148,35 @@ def webhook():
print("Stop Loss Price: " + str(stop_loss_price))

session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'],
qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False,
qty=qty, time_in_force="GoodTillCancel", reduce_only=False,
close_on_trigger=False, price=price, take_profit=take_profit_price, stop_loss=stop_loss_price)

elif data['order_mode'] == 'Profit':
take_profit_percent = float(data['take_profit_percent'])/100
current_price = session.latest_information_for_symbol(symbol=data['symbol'])['result'][0]['last_price']
if data['side'] == 'Buy':
take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent), 2)
elif data['side'] == 'Sell':
take_profit_price = round(float(current_price) - (float(current_price) * take_profit_percent), 2)

print("Take Profit Price: " + str(take_profit_price))
session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'],
qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False,
qty=qty, time_in_force="GoodTillCancel", reduce_only=False,
close_on_trigger=False, price=price, take_profit=take_profit_price)
elif data['order_mode'] == 'Stop':
stop_loss_percent = float(data['stop_loss_percent'])/100
current_price = session.latest_information_for_symbol(symbol=data['symbol'])['result'][0]['last_price']
if data['side'] == 'Buy':
stop_loss_price = round(float(current_price) - (float(current_price) * stop_loss_percent), 2)
elif data['side'] == 'Sell':
stop_loss_price = round(float(current_price) + (float(current_price) * stop_loss_percent), 2)

print("Stop Loss Price: " + str(stop_loss_price))
session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'],
qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False,
qty=qty, time_in_force="GoodTillCancel", reduce_only=False,
close_on_trigger=False, price=price, stop_loss=stop_loss_price)

else:
session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'],
qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False,
qty=qty, time_in_force="GoodTillCancel", reduce_only=False,
close_on_trigger=False, price=price)

return {
Expand All @@ -170,23 +186,25 @@ def webhook():
##############################################################################
# Binance Futures
##############################################################################
if data['exchange'] == 'binance-futures':
if use_binance_futures:
bot = Bot()
bot.run(data)
return {
"status": "success",
"message": "Binance Futures Webhook Received!"
}

else:
print("Invalid Exchange, Please Try Again!")
if data['exchange'] == 'binance-futures':
if use_binance_futures:
bot = Bot()
bot.run(data)
return {
"status": "error",
"message": "Invalid Exchange, Please Try Again!"
"status": "success",
"message": "Binance Futures Webhook Received!"
}
return {
"status": "error",
"message": "Binance Futures is not enabled or failed API validation."
}

else:
print("Invalid Exchange, Please Try Again!")
return {
"status": "error",
"message": "Invalid Exchange, Please Try Again!"
}

if __name__ == '__main__':
app.run(debug=False)


43 changes: 29 additions & 14 deletions binanceFutures.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
with open('config.json') as config_file:
config = json.load(config_file)

binance_config = config['EXCHANGES'].get('binance-futures') or config['EXCHANGES'].get('BINANCE-FUTURES')

if config['EXCHANGES']['binance-futures']['TESTNET']:
if binance_config['TESTNET']:
exchange = ccxt.binance({
'apiKey': config['EXCHANGES']['binance-futures']['API_KEY'],
'secret': config['EXCHANGES']['binance-futures']['API_SECRET'],
'apiKey': binance_config['API_KEY'],
'secret': binance_config['API_SECRET'],
'options': {
'defaultType': 'future',
},
Expand All @@ -24,8 +25,8 @@
exchange.set_sandbox_mode(True)
else:
exchange = ccxt.binance({
'apiKey': config['EXCHANGES']['binance-futures']['API_KEY'],
'secret': config['EXCHANGES']['binance-futures']['API_SECRET'],
'apiKey': binance_config['API_KEY'],
'secret': binance_config['API_SECRET'],
'options': {
'defaultType': 'future',
},
Expand All @@ -51,6 +52,20 @@ def create_string(self):
self.clientId = baseId + str(res)
return

def get_order_qty(self, data, current_price):
if 'qty_percent' not in data:
return float(data['qty'])

quote_currency = data.get('quote_currency') or data['symbol'].split('/')[-1]
balance = exchange.fetch_balance()
available = balance.get(quote_currency, {}).get('free')

if available is None:
available = balance.get('free', {}).get(quote_currency)

qty = (float(available) * (float(data['qty_percent']) / 100)) / float(current_price)
return float(exchange.amount_to_precision(data['symbol'], qty))

def close_position(self, symbol):
position = exchange.fetch_positions(symbol)[0]['info']['positionAmt']
self.create_string()
Expand Down Expand Up @@ -150,10 +165,12 @@ def run(self, data):
else:
price = 0

current_price = exchange.fetch_ticker(data['symbol'])['last']
qty = self.get_order_qty(data, current_price)

if data['order_mode'] == 'Both':
take_profit_percent = float(data['take_profit_percent']) / 100
stop_loss_percent = float(data['stop_loss_percent']) / 100
current_price = exchange.fetch_ticker(data['symbol'])['last']
if data['side'] == 'Buy':
take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent),
2)
Expand All @@ -172,18 +189,17 @@ def run(self, data):
'reduceOnly': False
}
if data['type'] == 'Limit':
exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']),
exchange.create_order(data['symbol'], data['type'], data['side'], qty,
price=float(price), params=params)
else:
exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']),
exchange.create_order(data['symbol'], data['type'], data['side'], qty,
params=params)

self.set_risk(data['symbol'], data, stop_loss_price, take_profit_price)


elif data['order_mode'] == 'Profit':
take_profit_percent = float(data['take_profit_percent']) / 100
current_price = exchange.fetch_ticker(data['symbol'])['last']

if data['side'] == 'Buy':
take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent),
Expand All @@ -201,18 +217,17 @@ def run(self, data):
}

if data['type'] == 'Limit':
exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']),
exchange.create_order(data['symbol'], data['type'], data['side'], qty,
price=float(price), params=params)
else:
exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']),
exchange.create_order(data['symbol'], data['type'], data['side'], qty,
params=params)

self.set_risk(data['symbol'], data, 0, take_profit_price)


elif data['order_mode'] == 'Stop':
stop_loss_percent = float(data['stop_loss_percent']) / 100
current_price = exchange.fetch_ticker(data['symbol'])['last']

if data['side'] == 'Buy':
stop_loss_price = round(float(current_price) - (float(current_price) * stop_loss_percent), 2)
Expand All @@ -228,10 +243,10 @@ def run(self, data):
}

if data['type'] == 'Limit':
exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']),
exchange.create_order(data['symbol'], data['type'], data['side'], qty,
price=float(price), params=params)
else:
exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']),
exchange.create_order(data['symbol'], data['type'], data['side'], qty,
params=params)

self.set_risk(data['symbol'], data, stop_loss_price, 0)
Expand Down