├── Procfile ├── requirements.txt ├── .gitignore ├── README.md ├── app.py └── oldapp /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn app:app -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | gunicorn 3 | python-binance 4 | line-notify 5 | pandas 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | *.db 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | .DS_Store? 34 | ._* 35 | .Spotlight-V100 36 | .Trashes 37 | ehthumbs.db 38 | Thumbs.db 39 | cache/* 40 | __pycache__/* 41 | */__pycache__/* 42 | *__pycache__/* 43 | env/* 44 | **/__pycache__/* 45 | config.sh 46 | config.ini 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tradingview-alert-webhook for binance-api 2 | TradingView Strategy Alert Webhook that buys and sells crypto with the Binance API 3 | This script work on both one-way mode and Hegde mode. 4 | # Script is compatible with the follwing strategy message 5 | ##### passphrase should be = SECRET_KEY 6 | ##### Open Position can use "$20" or "@0.02" for determined size In my case I can use "@xxx" as VXD auto calculate size 7 | ##### Close Position or TP can use "%xx" as this script will pull your position amount and calculated it, 8 | ##### for Example "amount": "%50" for TP 1 and "%100" for TP2 9 | 10 | # Sample payload 11 | ``` 12 | {"side":"OpenShort","amount":"@0.006","symbol":"BTCUSDTPERP","passphrase":"1234","leverage":"125"} 13 | ``` 14 | # There is 7 Vars Setting for HEROKU 15 | 1. API_KEY = your api key 16 | 2. API_SECRET = your api secret key 17 | 3. LINE_TOKEN = your Line-notify token can be genarated @https://notify-bot.line.me/en/ 18 | 4. BOT_NAME = any name 19 | 5. FREEBALANCE = Min balance for trade(Bot will Halted if FREEBALANCE < Equity) 20 | 6. SECRET_KEY = your passphrase form tradingview signal 21 | 7. ORDER_ENABLE = "TRUE" = Enable Bots "FALSE" = Disable Bots 22 | 23 | ``` 24 | passphrase = input.string(defval='xxxx', title ='Bot Pass',group='═ Bot Setting ═') 25 | leveragex = input.int(125,title='leverage',group='═ Bot Setting ═',tooltip='"NOTHING" to do with Position size',minval=1) 26 | Alert_OpenLong = '{"side": "OpenLong", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 27 | Alert_OpenShort = '{"side": "OpenShort", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 28 | Alert_LongTP = '{"side": "CloseLong", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 29 | Alert_ShortTP = '{"side": "CloseShort", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 30 | message_closelong = '{"side": "CloseLong", "amount": "%100", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 31 | message_closeshort = '{"side": "CloseShort", "amount": "%100", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 32 | ``` 33 | ## Vaz 34 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | # 3 | # Copyright (c) 2022 vazw. All rights reserved. 4 | # 5 | # Licensed under the "THE BEER-WARE LICENSE" (Revision 42): 6 | # Everyone is permitted to copy and distribute verbatim or modified 7 | # copies of this license document, and changing it is allowed as long 8 | # as the name is changed. 9 | # 10 | # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | # 0. You just DO WHAT THE FUCK YOU WANT TO. 13 | 14 | import json 15 | import os 16 | 17 | import pandas as pd 18 | from binance.client import Client 19 | from flask import Flask, request 20 | from line_notify import LineNotify 21 | 22 | API_KEY = f'{os.environ["API_KEY"]}' 23 | API_SECRET = f'{os.environ["API_SECRET"]}' 24 | LINE_TOKEN = f'{os.environ["LINE_TOKEN"]}' 25 | BOT_NAME = f'{os.environ["BOT_NAME"]}' 26 | FREEBALANCE = float(f'{os.environ["FREEBALANCE"]}') 27 | SECRET_KEY = f'{os.environ["SECRET_KEY"]}' 28 | ORDER_ENABLE = True if f'{os.environ["ORDER_ENABLE"]}' == "TRUE" else False 29 | app = Flask(__name__) 30 | client = Client(API_KEY, API_SECRET) 31 | notify = LineNotify(LINE_TOKEN) 32 | 33 | 34 | def change_leverage(data) -> dict: 35 | try: 36 | client.futures_change_leverage( 37 | symbol=data["symbol"], leverage=data["leverage"] 38 | ) 39 | return data 40 | except Exception as e: 41 | print(e) 42 | data["leverage"] = float( 43 | client.futures_position_information(symbol=data["symbol"])[ 44 | 1 if data["mode"] else 0 45 | ]["leverage"] 46 | ) 47 | return data 48 | 49 | 50 | def check_actions(actions) -> str: 51 | if actions == "CloseLong" or actions == "OpenShort": 52 | return "SELL" 53 | elif actions == "CloseShort" or actions == "OpenLong": 54 | return "BUY" 55 | elif actions == "test": 56 | return "test" 57 | else: 58 | return "test" 59 | 60 | 61 | def get_position_size(symbol) -> pd.DataFrame: 62 | positions = client.futures_position_information(symbol=symbol) 63 | current_position = [ 64 | position 65 | for position in positions 66 | if float(position["positionAmt"]) != 0 67 | ] 68 | position_data = pd.DataFrame( 69 | current_position, 70 | columns=[ 71 | "symbol", 72 | "entryPrice", 73 | "markPrice", 74 | "positionAmt", 75 | "unRealizedProfit", 76 | "positionSide", 77 | "leverage", 78 | ], 79 | ) 80 | return position_data 81 | 82 | 83 | def check_amount(symbol, order_amount, position_amount, action) -> float: 84 | qty_precision = 0 85 | m = len(order_amount) 86 | bids = float(client.futures_orderbook_ticker(symbol=symbol)["bidPrice"]) 87 | asks = float(client.futures_orderbook_ticker(symbol=symbol)["askPrice"]) 88 | bidask = bids if action == "SELL" else asks 89 | qty_precision = ( 90 | int(precistion["quantityPrecision"]) 91 | for precistion in client.futures_exchange_info()["symbols"] 92 | if precistion["symbol"] == symbol 93 | ).__next__() 94 | if order_amount[0] == "%": 95 | percent = float(order_amount[1:m]) 96 | return round(percent / 100 * position_amount, qty_precision) 97 | elif order_amount[0] == "@": 98 | fiat = float(order_amount[1:m]) 99 | return round(fiat, qty_precision) 100 | elif order_amount[0] == "$": 101 | usd = float(order_amount[1:m]) 102 | return round(usd / bidask, qty_precision) 103 | else: 104 | return 0 105 | 106 | 107 | def check_balance(fiat) -> float: 108 | balance = ( 109 | asset["balance"] 110 | for asset in client.futures_account_balance() 111 | if asset["asset"] == fiat 112 | ).__next__() 113 | return round(float(balance), 2) 114 | 115 | 116 | def close_order(data, position_data, side): 117 | order = client.futures_create_order( 118 | symbol=data["symbol"], 119 | positionSide=side, 120 | side=data["order_side"], 121 | type="MARKET", 122 | quantity=abs(data["amount"]), 123 | ) 124 | print(order) 125 | position_size = float(position_data["positionAmt"][data["symbol"]]) 126 | position_entry = float(position_data["entryPrice"][data["symbol"]]) 127 | position_lev = int(position_data["leverage"][data["symbol"]]) 128 | margin = position_entry * position_size / position_lev 129 | balance = check_balance("USDT") 130 | profit_loss = float( 131 | position_data["unRealizedProfit"][data["symbol"]] 132 | ) * abs(float(data["amount"]) / position_size) 133 | 134 | message = ( 135 | f"Binance Bot: {BOT_NAME}\n" 136 | + f"Coin : {data['symbol']}\n" 137 | + f"Order : {data['action']}\n" 138 | + f"Amount : {data['amount']}\n" 139 | + f"Margin : {round(margin, 2)}USDT\n" 140 | + f"P/L : {round(profit_loss, 2)} USDT\n" 141 | + f"Leverage : X{position_lev}\n" 142 | + f"Balance : {round(balance, 2)} USDT" 143 | ) 144 | return notify.send(message=message, sticker_id=1991, package_id=446) 145 | 146 | 147 | def open_order(data, side): 148 | data = change_leverage(data) 149 | order = client.futures_create_order( 150 | symbol=data["symbol"], 151 | positionSide=side, 152 | side=data["order_side"], 153 | type="MARKET", 154 | quantity=data["amount"], 155 | ) 156 | print(order) 157 | position_data = get_position_size(data["symbol"]) 158 | if data["mode"] and len(position_data.index) > 1: 159 | if data["action"] == "CloseLong": 160 | position_data.drop(index=1, inplace=True) 161 | if data["action"] == "OpenLong": 162 | position_data.drop(index=0, inplace=True) 163 | if data["action"] == "CloseShort": 164 | position_data.drop(index=0, inplace=True) 165 | if data["action"] == "OpenShort": 166 | position_data.drop(index=1, inplace=True) 167 | position_data = position_data.set_index("symbol") 168 | position_size = float(position_data["positionAmt"][data["symbol"]]) 169 | position_entry = float(position_data["entryPrice"][data["symbol"]]) 170 | position_lev = int(position_data["leverage"][data["symbol"]]) 171 | margin = position_entry * position_size / position_lev 172 | balance = check_balance("USDT") 173 | 174 | message = ( 175 | f"Binance Bot: {BOT_NAME}\n" 176 | + f"Coin : {data['symbol']}\n" 177 | + f"Order : {data['action']}\n" 178 | + f"Amount : {position_size}\n" 179 | + f"Margin : {round(margin, 2)}USDT\n" 180 | + f"Price : {position_entry}\n" 181 | + f"Leverage : X{position_lev}\n" 182 | + f"Balance : {round(balance, 2)} USDT" 183 | ) 184 | return notify.send(message=message, sticker_id=1997, package_id=446) 185 | 186 | 187 | def closeall_order(data, position_data, side): 188 | position_size = abs(float(position_data["positionAmt"][data["symbol"]])) 189 | position_entry = float(position_data["entryPrice"][data["symbol"]]) 190 | position_lev = int(position_data["leverage"][data["symbol"]]) 191 | 192 | order = client.futures_create_order( 193 | symbol=data["symbol"], 194 | positionSide=side, 195 | side=data["order_side"], 196 | type="MARKET", 197 | quantity=position_size, 198 | ) 199 | print(order) 200 | margin = position_entry * position_size / position_lev 201 | balance = check_balance("USDT") 202 | profit_loss = float(position_data["unRealizedProfit"][data["symbol"]]) 203 | 204 | message = ( 205 | f"Binance Bot: {BOT_NAME}\n" 206 | + f"Coin : {data['symbol']}\n" 207 | + "Order : CloseAll\n" 208 | + f"Amount : {position_size}\n" 209 | + f"Margin : {round(margin, 2)}USDT\n" 210 | + f"P/L : {round(profit_loss, 2)} USDT\n" 211 | + f"Leverage : X{position_lev}\n" 212 | + f"Balance : {round(balance, 2)} USDT" 213 | ) 214 | return notify.send(message=message, sticker_id=1988, package_id=446) 215 | 216 | 217 | def OpenLong(data): 218 | if data["amount_type"] == "%": 219 | return notify.send(f"{BOT_NAME : การตั้งค่าไม่ถูกต้อง}") 220 | return open_order(data, data["LongSide"]) 221 | 222 | 223 | def OpenShort(data): 224 | if data["amount_type"] == "%": 225 | return notify.send(f"{BOT_NAME : การตั้งค่าไม่ถูกต้อง}") 226 | return open_order(data, data["ShortSide"]) 227 | 228 | 229 | def CloseLong(data, position_data): 230 | return close_order(data, position_data, data["LongSide"]) 231 | 232 | 233 | def CloseShort(data, position_data): 234 | return close_order(data, position_data, data["ShortSide"]) 235 | 236 | 237 | def CloseAllLong(data, position_data): 238 | return closeall_order(data, position_data, data["LongSide"]) 239 | 240 | 241 | def CloseAllShort(data, position_data): 242 | return closeall_order(data, position_data, data["ShortSide"]) 243 | 244 | 245 | def ordering(order_data, position_data, position_size): 246 | isin_position = True if position_size != 0.0 else False 247 | if order_data["action"] == "CloseLong": 248 | if position_size > 0.0 and isin_position: 249 | CloseLong(order_data, position_data) 250 | return "Order Done" 251 | else: 252 | return "No Position : Do Nothing" 253 | elif order_data["action"] == "CloseShort": 254 | if position_size < 0.0 and isin_position: 255 | CloseShort(order_data, position_data) 256 | return "Order Done" 257 | else: 258 | return "No Position : Do Nothing" 259 | elif order_data["action"] == "OpenLong": 260 | if not order_data["mode"] and position_size < 0.0 and isin_position: 261 | CloseAllShort(order_data, position_data) 262 | OpenLong(order_data) 263 | return "Order Done" 264 | elif position_size > 0.0 and isin_position: 265 | return "Already in position : Do Nothing" 266 | else: 267 | OpenLong(order_data) 268 | return "Order Done" 269 | elif order_data["action"] == "OpenShort": 270 | if not order_data["mode"] and position_size > 0.0 and isin_position: 271 | CloseAllLong(order_data, position_data) 272 | OpenShort(order_data) 273 | return "Order Done" 274 | elif position_size < 0.0 and isin_position: 275 | return "Already in position : Do Nothing" 276 | else: 277 | OpenShort(order_data) 278 | return "Order Done" 279 | elif order_data["action"] == "test": 280 | return "test" 281 | else: 282 | return "Nothin to do" 283 | 284 | 285 | def signal_handle(data) -> str: 286 | """ 287 | Sample payload = '{"side":"OpenShort","amount":"@0.006","symbol":"BTCUSDTPERP","passphrase":"1945","leverage":"125"}' # noqa: 288 | """ 289 | if data["passphrase"] != SECRET_KEY: 290 | notify.send(f"{BOT_NAME} รหัสผ่านไม่ถูกต้อง") 291 | return "รหัสไม่ถูกต้อง :P" 292 | 293 | balance = check_balance("USDT") 294 | 295 | if float(balance) < FREEBALANCE: 296 | notify.send("ยอดเงินไม่พอ") 297 | return "ยอดเงินไม่พอ" 298 | 299 | symbol = data["symbol"] 300 | if (symbol[len(symbol) - 4 : len(symbol)]) == "PERP": 301 | symbol = symbol[0 : len(symbol) - 4] 302 | position_mode = client.futures_get_position_mode() 303 | position_data = get_position_size(symbol) 304 | position_size = 0.0 305 | if position_mode["dualSidePosition"] and len(position_data.index) > 1: 306 | if data["side"] == "CloseLong": 307 | position_data.drop(index=1, inplace=True) 308 | if data["side"] == "OpenLong": 309 | position_data.drop(index=0, inplace=True) 310 | if data["side"] == "CloseShort": 311 | position_data.drop(index=0, inplace=True) 312 | if data["side"] == "OpenShort": 313 | position_data.drop(index=1, inplace=True) 314 | if data["side"] == "test": 315 | return "test" 316 | position_data = position_data.set_index("symbol") 317 | if not position_data.empty: 318 | position_size = float(position_data["positionAmt"][symbol]) 319 | actions = check_actions((data["side"] if ORDER_ENABLE is True else "test")) 320 | amount = check_amount(symbol, data["amount"], position_size, actions) 321 | 322 | order_data = { 323 | "amount_type": data["amount"][0], 324 | "amount": amount, 325 | "symbol": symbol, 326 | "leverage": int(data["leverage"]), 327 | "action": (data["side"] if ORDER_ENABLE is True else "test"), 328 | "order_side": actions, 329 | "mode": position_mode["dualSidePosition"], 330 | "LongSide": ("LONG" if position_mode["dualSidePosition"] else "BOTH"), 331 | "ShortSide": ( 332 | "SHORT" if position_mode["dualSidePosition"] else "BOTH" 333 | ), 334 | "balance": balance, 335 | } 336 | 337 | try: 338 | message = ordering(order_data, position_data, position_size) 339 | return message 340 | except Exception as e: 341 | print(e) 342 | return f"{BOT_NAME} : เกิดข้อผิดพลาด\n{e}" 343 | 344 | 345 | @app.route("/") 346 | def first_pages(): 347 | return "hello" 348 | 349 | 350 | @app.route("/webhook", methods=["POST"]) 351 | def webhook(): 352 | data = json.loads(request.data) 353 | respone = signal_handle(data) 354 | notify.send(f"{respone}") 355 | return {"OK": "Done"} 356 | 357 | 358 | if __name__ == "__main__": 359 | app.run(debug=True) 360 | # print(get_position_size("OCEANUSDT")) 361 | # 362 | # test = signal_handle( 363 | # data={ 364 | # "side": "OpenLong", 365 | # "amount": "@574", 366 | # "symbol": "OCEANUSDT", 367 | # "passphrase": "8888", 368 | # "leverage": "20", 369 | # } 370 | # ) 371 | # print(test) 372 | -------------------------------------------------------------------------------- /oldapp: -------------------------------------------------------------------------------- 1 | # the following is the cryto trade bot and compatible with the follwing strategy message 2 | # var string bar1 = '════════ Password and Leverage ════════' 3 | # leveragex = input.string("20",group=bar1) 4 | # passphrase ="1234" 5 | # Alert_OpenLong = '{"side": "OpenLong", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 6 | # Alert_OpenShort = '{"side": "OpenShort", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 7 | # Alert_LongTP = '{"side": "CloseLong", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 8 | # Alert_ShortTP = '{"side": "CloseShort", "amount": "@{{strategy.order.contracts}}", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 9 | # message_closelong = '{"side": "CloseLong", "amount": "%100", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 10 | # message_closeshort = '{"side": "CloseShort", "amount": "%100", "symbol": "{{ticker}}", "passphrase": "'+passphrase+'","leverage":"'+str.tostring(leveragex)+'"}' 11 | # Sample payload = '{"side":"OpenShort","amount":"@0.006","symbol":"BTCUSDTPERP","passphrase":"1945","leverage":"125"}' 12 | # mod and dev by DR.AKN 13 | 14 | # feature 15 | import json 16 | import os 17 | import sys 18 | import time 19 | 20 | import requests 21 | from binance.client import Client 22 | from binance.enums import * 23 | from flask import Flask, render_template, request 24 | 25 | app = Flask(__name__) 26 | 27 | API_KEY = str(os.environ["API_KEY"]) 28 | API_SECRET = str(os.environ["API_SECRET"]) 29 | LINE_TOKEN = str(os.environ["LINE_TOKEN"]) 30 | BOT_NAME = str(os.environ["BOT_NAME"]) 31 | FREEBALANCE = str(os.environ["FREEBALANCE"]) 32 | SECRET_KEY = str(os.environ["SECRET_KEY"]) 33 | ORDER_ENABLE = str(os.environ["ORDER_ENABLE"]) 34 | # set order enable = FALSE in vars when want to test nonorder api cmd./TRUE for normal operation 35 | # client = Client(API_KEY,API_SECRET,testnet=TEST_NET) 36 | client = Client(API_KEY, API_SECRET) 37 | 38 | url = "https://notify-api.line.me/api/notify" 39 | headers = { 40 | "content-type": "application/x-www-form-urlencoded", 41 | "Authorization": "Bearer " + LINE_TOKEN, 42 | } 43 | 44 | 45 | @app.route("/") 46 | def hello_world(): 47 | return render_template("index.html") 48 | 49 | 50 | @app.route("/webhook", methods=["POST"]) 51 | def webhook(): 52 | data = json.loads(request.data) 53 | print("Received Signal.......") 54 | passphrase = data["passphrase"] 55 | # check if secretkey is valid 56 | if passphrase != SECRET_KEY: 57 | print("Invalid SECRET KEY/PASSPHRASE") 58 | return {"code": "fail", "message": "denied : nice try."} 59 | print("Valid SECRET KEY/PASSPHRASE") 60 | # Enabletrade. 61 | if ORDER_ENABLE == "TRUE": 62 | action = data["side"] 63 | else: 64 | action = "test" 65 | 66 | amount = data["amount"] 67 | symbol = data["symbol"] 68 | lev = data["leverage"] 69 | # separate amount type 70 | fiat = 0 71 | usdt = 0 72 | percent = 0 73 | idl = 0 74 | ids = 0 75 | Lside = "BOTH" 76 | Sside = "BOTH" 77 | 78 | currentmode = client.futures_get_position_mode() 79 | if currentmode["dualSidePosition"] == True: 80 | print("Position mode: Hedge Mode") 81 | idl = 1 82 | ids = 2 83 | Lside = "LONG" 84 | Sside = "SHORT" 85 | else: 86 | print("Position mode: OneWay Mode") 87 | 88 | # trim PERP from symbol 89 | if (symbol[len(symbol) - 4 : len(symbol)]) == "PERP": 90 | symbol = symbol[0 : len(symbol) - 4] 91 | 92 | COIN = symbol[0 : len(symbol) - 4] 93 | 94 | if amount[0] == "@": 95 | fiat = float(amount[1 : len(amount)]) 96 | print( 97 | "COIN>>", 98 | symbol, 99 | " : ", 100 | action, 101 | " : amount=", 102 | fiat, 103 | " : leverage=", 104 | lev, 105 | ) 106 | if amount[0] == "$": 107 | usdt = float(amount[1 : len(amount)]) 108 | print( 109 | "USDT>>", 110 | symbol, 111 | " : ", 112 | action, 113 | " : amount=", 114 | usdt, 115 | " : leverage=", 116 | lev, 117 | ) 118 | if amount[0] == "%": 119 | percent = float(amount[1 : len(amount)]) 120 | print( 121 | "Percent>>", 122 | symbol, 123 | " : ", 124 | action, 125 | " : amount=", 126 | percent, 127 | " : leverage=", 128 | lev, 129 | ) 130 | 131 | ask = 0 132 | bid = 0 133 | new_balance = 0 134 | posiAmt = 0 135 | unpnl = 0 136 | min_balance = 0 137 | usdt = float(usdt) 138 | lev = int(lev) 139 | 140 | # check USDT Balance 141 | balance_index = 0 142 | balance_list = client.futures_account_balance() 143 | print(len(balance_list)) 144 | for i in range(0, (len(balance_list) - 1), 1): 145 | # print("asset=",balance_list[i]['asset']) 146 | if balance_list[i]["asset"] == "USDT": 147 | balance_index = i 148 | break 149 | balance_key = "balance" 150 | balance = float( 151 | client.futures_account_balance()[balance_index][balance_key] 152 | ) 153 | print("USDT Balance=", balance, " USDT") 154 | 155 | # print(FREEBALANCE[0]) 156 | if FREEBALANCE[0] == "$": 157 | min_balance = float(FREEBALANCE[1 : len(FREEBALANCE)]) 158 | print("FREEBALANCE=", min_balance, " USDT") 159 | # Alertline if balance 0.0: 338 | qty_precision = 0 339 | for j in client.futures_exchange_info()["symbols"]: 340 | if j["symbol"] == symbol: 341 | qty_precision = int(j["quantityPrecision"]) 342 | print("qty_precision", qty_precision) 343 | # check if sell in % or $ 344 | if amount[0] == "%": 345 | qty_close = round(percent * posiAmt / 100, qty_precision) 346 | usdt = round(qty_close * bid, qty_precision) 347 | print( 348 | "SELL/CloseLong by % amount=", 349 | qty_close, 350 | " ", 351 | COIN, 352 | ": USDT=", 353 | round(usdt, 3), 354 | ) 355 | if amount[0] == "$": 356 | usdt = float(amount[1 : len(amount)]) 357 | qty_close = round(usdt / bid, qty_precision) 358 | print( 359 | "SELL/CloseLong by USDT amount=", 360 | usdt, 361 | ": COIN", 362 | round(qty_close, 3), 363 | ) 364 | if amount[0] == "@": 365 | fiat = float(amount[1 : len(amount)]) 366 | qty_close = round(fiat, qty_precision) 367 | usdt = round(fiat * bid, qty_precision) 368 | print( 369 | "SELL/CloseLong by @ amount=", 370 | fiat, 371 | " ", 372 | COIN, 373 | ": USDT=", 374 | round(usdt, 3), 375 | ) 376 | if abs(qty_close) > abs(posiAmt): 377 | qty_close = abs(posiAmt) 378 | print( 379 | "Confirm:", 380 | symbol, 381 | ":", 382 | action, 383 | ": Qty=", 384 | qty_close, 385 | " ", 386 | COIN, 387 | ":USDT=", 388 | round(usdt, 3), 389 | ) 390 | qty_close = abs(round(qty_close, qty_precision)) 391 | leverage = float( 392 | client.futures_position_information(symbol=symbol)[idl][ 393 | "leverage" 394 | ] 395 | ) 396 | entryP = float( 397 | client.futures_position_information(symbol=symbol)[idl][ 398 | "entryPrice" 399 | ] 400 | ) 401 | close_BUY = client.futures_create_order( 402 | symbol=symbol, 403 | positionSide=Lside, 404 | side="SELL", 405 | type="MARKET", 406 | quantity=qty_close, 407 | ) 408 | time.sleep(1) 409 | # success close sell, push line notification 410 | new_balance = float( 411 | client.futures_account_balance()[balance_index][balance_key] 412 | ) 413 | ROI = (bid - entryP) / entryP * 100 * leverage 414 | profit = unpnl * abs(qty_close / posiAmt) 415 | print("Margin %ROE=", ROI) 416 | msg = ( 417 | "BINANCE:\n" 418 | + "BOT : " 419 | + BOT_NAME 420 | + "\nCoin : " 421 | + COIN 422 | + "/USDT" 423 | + "\nStatus : " 424 | + action 425 | + "[SELL]" 426 | + "\nAmount : " 427 | + str(qty_close) 428 | + " " 429 | + COIN 430 | + "(" 431 | + str(round((qty_close * bid), 2)) 432 | + " USDT)" 433 | + "\nPrice : " 434 | + str(bid) 435 | + " USDT" 436 | + "\nLeverage : X" 437 | + str(round(leverage)) 438 | + "\n%ROE :" 439 | + str(round(ROI, 2)) 440 | + "%" 441 | + "\nRealized P/L: " 442 | + str(round(profit, 2)) 443 | + " USDT" 444 | + "\nBalance :" 445 | + str(round(new_balance, 2)) 446 | + " USDT" 447 | ) 448 | r = requests.post(url, headers=headers, data={"message": msg}) 449 | print(symbol, ": Close Long Position Excuted") 450 | else: 451 | print("Do not have any Long Position on ", symbol) 452 | 453 | # OpenLong/BUY 454 | if action == "OpenLong": 455 | qty_precision = 0 456 | for j in client.futures_exchange_info()["symbols"]: 457 | if j["symbol"] == symbol: 458 | qty_precision = int(j["quantityPrecision"]) 459 | # check if buy in @ or fiat 460 | if amount[0] == "@": 461 | fiat = float(amount[1 : len(amount)]) 462 | Qty_buy = round(fiat, qty_precision) 463 | usdt = round(fiat * ask, qty_precision) 464 | print( 465 | "BUY/LONG by @ amount=", 466 | fiat, 467 | " ", 468 | COIN, 469 | ": USDT=", 470 | round(usdt, 3), 471 | ) 472 | if amount[0] == "$": 473 | usdt = float(amount[1 : len(amount)]) 474 | Qty_buy = round(usdt / ask, qty_precision) 475 | print("BUY/LONG by USDT amount=", usdt, ": COIN", round(usdt, 30)) 476 | print( 477 | "Confirm:", 478 | symbol, 479 | ":", 480 | action, 481 | ":Qty=", 482 | Qty_buy, 483 | " ", 484 | COIN, 485 | ":USDT=", 486 | round(usdt, 3), 487 | ) 488 | Qty_buy = abs(round(Qty_buy, qty_precision)) 489 | print("qty buy : ", Qty_buy) 490 | try: 491 | client.futures_change_leverage(symbol=symbol, leverage=lev) 492 | except: 493 | lev = float( 494 | client.futures_position_information(symbol=symbol)[idl][ 495 | "leverage" 496 | ] 497 | ) 498 | print("leverage : X", lev) 499 | order_BUY = client.futures_create_order( 500 | symbol=symbol, 501 | positionSide=Lside, 502 | side="BUY", 503 | type="MARKET", 504 | quantity=Qty_buy, 505 | ) 506 | time.sleep(1) 507 | # get entry price to find margin value 508 | entryP = float( 509 | client.futures_position_information(symbol=symbol)[idl][ 510 | "entryPrice" 511 | ] 512 | ) 513 | print("entryP=", entryP) 514 | margin = entryP * Qty_buy / lev 515 | # success openlong, push line notification 516 | new_balance = float( 517 | client.futures_account_balance()[balance_index][balance_key] 518 | ) 519 | print("Old Balance=", balance) 520 | print("New Balance=", new_balance) 521 | msg = ( 522 | "BINANCE:\n" 523 | + "BOT :" 524 | + BOT_NAME 525 | + "\nCoin :" 526 | + COIN 527 | + "/USDT" 528 | + "\nStatus :" 529 | + action 530 | + "[BUY]" 531 | + "\nAmount :" 532 | + str(Qty_buy) 533 | + " " 534 | + COIN 535 | + "/" 536 | + str(usdt) 537 | + " USDT" 538 | + "\nPrice :" 539 | + str(ask) 540 | + " USDT" 541 | + "\nLeverage: X" 542 | + str(round(lev)) 543 | + "\nMargin :" 544 | + str(round(margin, 2)) 545 | + " USDT" 546 | + "\nBalance :" 547 | + str(round(new_balance, 2)) 548 | + " USDT" 549 | ) 550 | r = requests.post(url, headers=headers, data={"message": msg}) 551 | print(symbol, " : Open Long Position Excuted") 552 | 553 | # OpenShort/SELL 554 | if action == "OpenShort": 555 | qty_precision = 0 556 | for j in client.futures_exchange_info()["symbols"]: 557 | if j["symbol"] == symbol: 558 | qty_precision = int(j["quantityPrecision"]) 559 | # check if sell in @ or fiat 560 | if amount[0] == "@": 561 | fiat = float(amount[1 : len(amount)]) 562 | Qty_sell = round(fiat, qty_precision) 563 | usdt = round(fiat * bid, qty_precision) 564 | print( 565 | "SELL/SHORT by @ amount=", 566 | fiat, 567 | " ", 568 | COIN, 569 | ": USDT=", 570 | round(usdt, 3), 571 | ) 572 | if amount[0] == "$": 573 | usdt = float(amount[1 : len(amount)]) 574 | Qty_sell = round(usdt / bid, qty_precision) 575 | print( 576 | "SELL/SHORT by USDT amount=", usdt, ": COIN", round(usdt, 30) 577 | ) 578 | print( 579 | "Confirm:", 580 | symbol, 581 | ":", 582 | action, 583 | ": Qty=", 584 | Qty_sell, 585 | " ", 586 | COIN, 587 | ":USDT=", 588 | round(usdt, 3), 589 | ) 590 | Qty_sell = abs(round(Qty_sell, qty_precision)) 591 | print("qty sell : ", Qty_sell) 592 | try: 593 | client.futures_change_leverage(symbol=symbol, leverage=lev) 594 | except: 595 | lev = float( 596 | client.futures_position_information(symbol=symbol)[ids][ 597 | "leverage" 598 | ] 599 | ) 600 | print("leverage : X", lev) 601 | order_SELL = client.futures_create_order( 602 | symbol=symbol, 603 | positionSide=Sside, 604 | side="SELL", 605 | type="MARKET", 606 | quantity=Qty_sell, 607 | ) 608 | time.sleep(1) 609 | # get entry price to find margin value 610 | entryP = float( 611 | client.futures_position_information(symbol=symbol)[ids][ 612 | "entryPrice" 613 | ] 614 | ) 615 | print("entryP=", entryP) 616 | margin = entryP * Qty_sell / lev 617 | # success openlong, push line notification 618 | new_balance = float( 619 | client.futures_account_balance()[balance_index][balance_key] 620 | ) 621 | print("Old Balance=", balance) 622 | print("New Balance=", new_balance) 623 | # success openshort, push line notification 624 | msg = ( 625 | "BINANCE:\n" 626 | + "BOT :" 627 | + BOT_NAME 628 | + "\nCoin :" 629 | + COIN 630 | + "/USDT" 631 | + "\nStatus :" 632 | + action 633 | + "[SELL]" 634 | + "\nAmount :" 635 | + str(Qty_sell) 636 | + " " 637 | + COIN 638 | + "/" 639 | + str(usdt) 640 | + " USDT" 641 | + "\nPrice :" 642 | + str(bid) 643 | + " USDT" 644 | + "\nLeverage: X" 645 | + str(round(lev)) 646 | + "\nMargin :" 647 | + str(round(margin, 2)) 648 | + " USDT" 649 | + "\nBalance :" 650 | + str(round(new_balance, 2)) 651 | + " USDT" 652 | ) 653 | r = requests.post(url, headers=headers, data={"message": msg}) 654 | print(symbol, ": Open Short Position Excuted") 655 | 656 | # test/Position info 657 | if action == "test": 658 | msgL = "" 659 | msgS = "" 660 | msgB = "" 661 | # OneWay 662 | if currentmode["dualSidePosition"] is not True: 663 | amount = float( 664 | client.futures_position_information(symbol=symbol)[0][ 665 | "positionAmt" 666 | ] 667 | ) 668 | if amount > 0: 669 | print( 670 | "Long amount : ", 671 | float( 672 | client.futures_position_information(symbol=symbol)[0][ 673 | "positionAmt" 674 | ] 675 | ), 676 | ) 677 | entry = float( 678 | client.futures_position_information(symbol=symbol)[0][ 679 | "entryPrice" 680 | ] 681 | ) 682 | print( 683 | "Long Entry : ", 684 | float( 685 | client.futures_position_information(symbol=symbol)[0][ 686 | "entryPrice" 687 | ] 688 | ), 689 | ) 690 | upnl = float( 691 | client.futures_position_information(symbol=symbol)[0][ 692 | "unRealizedProfit" 693 | ] 694 | ) 695 | print( 696 | "Unrealized PNL:", 697 | float( 698 | client.futures_position_information(symbol=symbol)[0][ 699 | "unRealizedProfit" 700 | ] 701 | ), 702 | "USDT", 703 | ) 704 | leverage = float( 705 | client.futures_position_information(symbol=symbol)[0][ 706 | "leverage" 707 | ] 708 | ) 709 | print( 710 | "Leverage : ", 711 | float( 712 | client.futures_position_information(symbol=symbol)[0][ 713 | "leverage" 714 | ] 715 | ), 716 | ) 717 | margin = entry * amount / leverage 718 | print("Margin : ", round(margin, 2), " USDT") 719 | ROI = (bid - entry) / entry * 100 * leverage 720 | print("Long %ROE : ", ROI) 721 | msgB = ( 722 | "\nLong Entry : " 723 | + str( 724 | float( 725 | client.futures_position_information(symbol=symbol)[ 726 | 0 727 | ]["entryPrice"] 728 | ) 729 | ) 730 | + "\nLong amount : " 731 | + str( 732 | float( 733 | client.futures_position_information(symbol=symbol)[ 734 | 0 735 | ]["positionAmt"] 736 | ) 737 | ) 738 | + COIN 739 | + "(" 740 | + str(round((amoutL * bid), 2)) 741 | + " USDT)" 742 | + "\nLeverage :X" 743 | + str(round(leverage)) 744 | + "\nMargin : " 745 | + str(round(margin, 2)) 746 | + " USDT\n%ROE : " 747 | + str(round(ROI, 2)) 748 | + "%" 749 | + "\nUnrealized P/L: " 750 | + str( 751 | round( 752 | float( 753 | client.futures_position_information( 754 | symbol=symbol 755 | )[0]["unRealizedProfit"] 756 | ), 757 | 2, 758 | ) 759 | ) 760 | + " USDT" 761 | + "\n -------------" 762 | ) 763 | print("---------------------------") 764 | 765 | if amount < 0: 766 | print( 767 | "Short amount : ", 768 | float( 769 | client.futures_position_information(symbol=symbol)[0][ 770 | "positionAmt" 771 | ] 772 | ), 773 | ) 774 | entry = float( 775 | client.futures_position_information(symbol=symbol)[0][ 776 | "entryPrice" 777 | ] 778 | ) 779 | print( 780 | "Short Entry : ", 781 | float( 782 | client.futures_position_information(symbol=symbol)[0][ 783 | "entryPrice" 784 | ] 785 | ), 786 | ) 787 | upnl = float( 788 | client.futures_position_information(symbol=symbol)[0][ 789 | "unRealizedProfit" 790 | ] 791 | ) 792 | print( 793 | "Unrealized PNL:", 794 | float( 795 | client.futures_position_information(symbol=symbol)[0][ 796 | "unRealizedProfit" 797 | ] 798 | ), 799 | "USDT", 800 | ) 801 | leverage = float( 802 | client.futures_position_information(symbol=symbol)[0][ 803 | "leverage" 804 | ] 805 | ) 806 | print( 807 | "Leverage : ", 808 | float( 809 | client.futures_position_information(symbol=symbol)[0][ 810 | "leverage" 811 | ] 812 | ), 813 | ) 814 | margin = entry * amount / leverage 815 | print("Margin : ", round(margin, 2), " USDT") 816 | ROI = (entry - ask) / entry * 100 * leverage 817 | print("Short %ROE : ", ROI) 818 | msgB = ( 819 | "\nShort Entry : " 820 | + str( 821 | float( 822 | client.futures_position_information(symbol=symbol)[ 823 | 0 824 | ]["entryPrice"] 825 | ) 826 | ) 827 | + "\nLong amount : " 828 | + str( 829 | abs( 830 | float( 831 | client.futures_position_information( 832 | symbol=symbol 833 | )[0]["positionAmt"] 834 | ) 835 | ) 836 | ) 837 | + COIN 838 | + "(" 839 | + str(round((amoutL * bid), 2)) 840 | + " USDT)" 841 | + "\nLeverage :X" 842 | + str(round(leverage)) 843 | + "\nMargin : " 844 | + str(round(margin, 2)) 845 | + " USDT\n%ROE : " 846 | + str(round(ROI, 2)) 847 | + "%" 848 | + "\nUnrealized P/L: " 849 | + str( 850 | round( 851 | float( 852 | client.futures_position_information( 853 | symbol=symbol 854 | )[0]["unRealizedProfit"] 855 | ), 856 | 2, 857 | ) 858 | ) 859 | + " USDT" 860 | + "\n -------------" 861 | ) 862 | print("---------------------------") 863 | 864 | # Hedge 865 | else: 866 | ROIB = 0 867 | ROIS = 0 868 | amoutL = abs( 869 | float( 870 | client.futures_position_information(symbol=symbol)[1][ 871 | "positionAmt" 872 | ] 873 | ) 874 | ) 875 | amoutS = abs( 876 | float( 877 | client.futures_position_information(symbol=symbol)[2][ 878 | "positionAmt" 879 | ] 880 | ) 881 | ) 882 | print("Position info :") 883 | print("---------------------------") 884 | if amoutL > 0: 885 | print( 886 | "Long amount:", 887 | float( 888 | client.futures_position_information(symbol=symbol)[1][ 889 | "positionAmt" 890 | ] 891 | ), 892 | COIN, 893 | ) 894 | entryPB = float( 895 | client.futures_position_information(symbol=symbol)[1][ 896 | "entryPrice" 897 | ] 898 | ) 899 | print( 900 | "Long Entry :", 901 | float( 902 | client.futures_position_information(symbol=symbol)[1][ 903 | "entryPrice" 904 | ] 905 | ), 906 | ) 907 | print( 908 | "Long Unrealized PNL:", 909 | float( 910 | client.futures_position_information(symbol=symbol)[1][ 911 | "unRealizedProfit" 912 | ] 913 | ), 914 | "USDT", 915 | ) 916 | leverage = float( 917 | client.futures_position_information(symbol=symbol)[1][ 918 | "leverage" 919 | ] 920 | ) 921 | print( 922 | "Leverage :X", 923 | float( 924 | client.futures_position_information(symbol=symbol)[1][ 925 | "leverage" 926 | ] 927 | ), 928 | ) 929 | margin = entryPB * amoutL / leverage 930 | print("Margin :", round(margin, 2), " USDT") 931 | if entryPB > 0: 932 | ROIB = (ask - entryPB) / entryPB * 100 * leverage 933 | print("Long %ROE=", ROIB) 934 | msgL = ( 935 | "\nLong Entry : " 936 | + str( 937 | float( 938 | client.futures_position_information(symbol=symbol)[ 939 | 1 940 | ]["entryPrice"] 941 | ) 942 | ) 943 | + "\nLong amount : " 944 | + str( 945 | float( 946 | client.futures_position_information(symbol=symbol)[ 947 | 1 948 | ]["positionAmt"] 949 | ) 950 | ) 951 | + COIN 952 | + "(" 953 | + str(round((amoutL * ask), 2)) 954 | + " USDT)" 955 | + "\nLeverage :X" 956 | + str(round(leverage)) 957 | + "\nMargin : " 958 | + str(round(margin, 2)) 959 | + " USDT\n%ROE : " 960 | + str(round(ROIB, 2)) 961 | + "%" 962 | + "\nUnrealized P/L: " 963 | + str( 964 | round( 965 | float( 966 | client.futures_position_information( 967 | symbol=symbol 968 | )[1]["unRealizedProfit"] 969 | ), 970 | 2, 971 | ) 972 | ) 973 | + " USDT" 974 | + "\n -------------" 975 | ) 976 | print("---------------------------") 977 | if amoutS > 0: 978 | print( 979 | "Short amount:", 980 | float( 981 | client.futures_position_information(symbol=symbol)[2][ 982 | "positionAmt" 983 | ] 984 | ), 985 | COIN, 986 | ) 987 | entryPS = float( 988 | client.futures_position_information(symbol=symbol)[2][ 989 | "entryPrice" 990 | ] 991 | ) 992 | print( 993 | "Short Entry :", 994 | float( 995 | client.futures_position_information(symbol=symbol)[2][ 996 | "entryPrice" 997 | ] 998 | ), 999 | ) 1000 | print( 1001 | "Short Unrealized PNL:", 1002 | float( 1003 | client.futures_position_information(symbol=symbol)[2][ 1004 | "unRealizedProfit" 1005 | ] 1006 | ), 1007 | "USDT", 1008 | ) 1009 | leverage = float( 1010 | client.futures_position_information(symbol=symbol)[2][ 1011 | "leverage" 1012 | ] 1013 | ) 1014 | print( 1015 | "Leverage :X", 1016 | float( 1017 | client.futures_position_information(symbol=symbol)[2][ 1018 | "leverage" 1019 | ] 1020 | ), 1021 | ) 1022 | margin = entryPS * amoutS / leverage 1023 | print("Margin :", round(margin, 2), " USDT") 1024 | if entryPS > 0: 1025 | ROIS = (entryPS - bid) / entryPS * 100 * leverage 1026 | print("Short %ROE=", ROIS) 1027 | msgS = ( 1028 | "\nShort Entry : " 1029 | + str( 1030 | float( 1031 | client.futures_position_information(symbol=symbol)[ 1032 | 2 1033 | ]["entryPrice"] 1034 | ) 1035 | ) 1036 | + "\nShort amount : " 1037 | + str( 1038 | abs( 1039 | float( 1040 | client.futures_position_information( 1041 | symbol=symbol 1042 | )[2]["positionAmt"] 1043 | ) 1044 | ) 1045 | ) 1046 | + COIN 1047 | + "(" 1048 | + str(round((amoutS * bid), 2)) 1049 | + " USDT)" 1050 | + "\nLeverage :X" 1051 | + str(round(leverage)) 1052 | + "\nMargin : " 1053 | + str(round(margin, 2)) 1054 | + " USDT\n%ROE : " 1055 | + str(round(ROIS, 2)) 1056 | + "%" 1057 | + "\nUnrealized P/L: " 1058 | + str( 1059 | round( 1060 | float( 1061 | client.futures_position_information( 1062 | symbol=symbol 1063 | )[2]["unRealizedProfit"] 1064 | ), 1065 | 2, 1066 | ) 1067 | ) 1068 | + " USDT" 1069 | + "\n -------------" 1070 | ) 1071 | print("---------------------------") 1072 | print( 1073 | "If position amount is = your real position in binance you are good to GO!" 1074 | ) 1075 | print("If something is off please re-check all Setting.") 1076 | print("---------------------------") 1077 | msg = ( 1078 | "BINANCE:\n" 1079 | + "BOT : " 1080 | + BOT_NAME 1081 | + "\nPosition info : " 1082 | + COIN 1083 | + "/USDT" 1084 | + msgB 1085 | + msgL 1086 | + msgS 1087 | + "\nBalance : " 1088 | + str(round(balance, 2)) 1089 | + " USDT" 1090 | ) 1091 | r = requests.post(url, headers=headers, data={"message": msg}) 1092 | 1093 | print("██╗░░░██╗░█████╗░███████╗") 1094 | print("██║░░░██║██╔══██╗╚════██║") 1095 | print("╚██╗░██╔╝███████║░░███╔═╝") 1096 | print("░╚████╔╝░██╔══██║██╔══╝░░") 1097 | print("░░╚██╔╝░░██║░░██║███████╗") 1098 | print("by.╚═╝░░░╚═╝░░╚═╝╚══════╝") 1099 | 1100 | return {"code": "success", "message": "Oki"} 1101 | 1102 | 1103 | if __name__ == "__main__": 1104 | app.run(debug=True) 1105 | --------------------------------------------------------------------------------