├── Procfile ├── runtime.txt ├── requirements.txt ├── .gitignore ├── .idea └── .gitignore ├── config.json ├── Dockerfile ├── README.md ├── app.py └── binanceFutures.py /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn app:app -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.11.2 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pybit @ git+https://github.com/CryptoGnome/pybit-gnome.git@e86059a8a7a36be6b49f173f44affbb515603337 2 | flask 3 | gunicorn 4 | ccxt==3.0.74 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea/inspectionProfiles/profiles_settings.xml 3 | .idea/inspectionProfiles/Project_Default.xml 4 | .idea/misc.xml 5 | .idea/modules.xml 6 | .idea/Tradingview-Webhook-Bot.iml 7 | .idea/vcs.xml 8 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "KEY": 12345, 3 | "EXCHANGES": { 4 | "BYBIT": { 5 | "API_KEY": "api-key-goes-here", 6 | "API_SECRET": "api-secret-goes-here", 7 | "ENABLED": true, 8 | "TESTNET": false 9 | }, 10 | "BINANCE-FUTURES": { 11 | "API_KEY": "api-key-goes-here", 12 | "API_SECRET": "api-secret-goes-here", 13 | "ENABLED": false, 14 | "TESTNET": false 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official Python base image 2 | FROM python:3.11 3 | 4 | # Set the working directory inside the container 5 | WORKDIR /app 6 | 7 | # Copy the requirements.txt file into the container 8 | COPY requirements.txt ./ 9 | 10 | # Install any needed packages specified in requirements.txt 11 | RUN apt-get update && apt-get install -y nano && \ 12 | pip install --trusted-host pypi.python.org -r requirements.txt 13 | 14 | # Copy the rest of your project's source code into the container 15 | COPY . . 16 | 17 | # Make port 5000 available to the world outside this container 18 | EXPOSE 5005 19 | 20 | # Define environment variable 21 | ENV FLASK_APP=app.py 22 | 23 | # Run your application when the container launches 24 | CMD ["flask", "run", "--host=0.0.0.0", "--port=5005"] 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Gnome-YT](https://user-images.githubusercontent.com/33667144/176252098-b38ed127-2c3e-41c4-9f4f-d3187da37368.jpg) 3 | 4 | This is a tradingview webhook designed to be free & open source. This bot is written using Python & Flask and is designed to run a free heroku server. It will allow you to create custom alerts in tradingview and send them to your own private webhook server that can place trades on your account via the api. 5 | 6 | #### Support can be requested in our Discord: 7 | 8 | https://discord.gg/Qb9unmxD6D 9 | 10 | #### Current Exchanges 11 | - [Bybit](https://partner.bybit.com/b/webhookbot) 12 | - [Binance Futures](https://www.binance.com/en/register?ref=LMFD8MJ5) 13 | - More will be done on request or can be added by submitting a pull request. 14 | 15 |
16 | 17 | ***Help keep this tool free by creating a new account using our referral links below:*** 18 | ------------------- 19 | [Tradingview](https://www.tradingview.com/?offer_id=10&aff_id=9584) 20 | 21 | [Create Bybit Account](https://partner.bybit.com/b/webhookbot) 22 | 23 | [Create Binance Futures Account](https://www.binance.com/en/register?ref=LMFD8MJ5) 24 | 25 |
26 |
27 | 28 | 29 | #### Video Tutorial: 30 | https://youtu.be/VX68RrMvM5Q 31 | 32 | 33 |
34 |
35 | 36 | # How to Webhook Server on Heroku 37 | 38 | 1.) Clone Project to Desktop 39 | 40 | 2.) [Create a Heroku Account](https://www.heroku.com/) 41 | 42 | *Heroku was free, now costs only $7 but is worth it... you are investing you money here and you want to do it right.* 43 | 44 | 3.) Edit config.json to add your own api keys & add a custom key to protect the server. 45 | 46 | ```You need to create new keys on Bybit & give them the correct acess to trade and see token balance``` 47 | 48 | 4.) Open a terminal in the cloned directory: 49 | 50 | 5.) Install Heroku CLI so you can work connect you your webserver. 51 | 52 | https://cli-assets.heroku.com/heroku-x64.exe 53 | 54 | 55 | 6.) Submit the following lines into the terminal and press ENTER after each one to procces the code: 56 | 57 | 58 | ``git init`` 59 | 60 | ``heroku login`` 61 | 62 | ``heroku create --region eu tv-trader-yourservernamehere`` 63 | 64 | ``git add .`` 65 | 66 | ``git commit -m "Initial Commit"`` 67 | 68 | ``git push heroku master`` 69 | 70 | 71 | ***Anytime you need to make a change to the code or the API keys, you can push a new build to Heroku:*** 72 | 73 | ``git add .`` 74 | 75 | ``git commit -m "Update"`` 76 | 77 | ``git push heroku master`` 78 | 79 | # How to send alerts from TradingView to your new Webserver 80 | 81 | After starting you server, you shoudl see an address that will allow you to access it like below: 82 | 83 | [https://tv-trader-gnome.herokuapp.com/webhook](https://tv-trader-gnome.herokuapp.com/webhook) 84 | 85 | #### You will want to add this when you create a new alert like show below: 86 | 87 | ![image](https://user-images.githubusercontent.com/33667144/176002365-be54dfdc-690a-433d-9702-e8e9641a45b5.png) 88 | 89 | #### You will then want to create you syntax based on the format shownb below and place it in the alert msg field 90 | 91 | ![image](https://user-images.githubusercontent.com/33667144/176003033-26794889-e041-4737-83f1-4f850335f280.png) 92 | 93 | 94 | _Now when your alerts fire off they should go strait to your server and get proccessed on the exchange almost instantly!_ 95 | 96 | 97 | # TradingView Alerts Format 98 | 99 | ``` 100 | { 101 | "key": "678777", 102 | "exchange": "bybit", 103 | "symbol": "ETHUSD", 104 | "type": "Market", 105 | "side": "Buy", 106 | "qty": "1", 107 | "price": "1120", 108 | "close_position": "False", 109 | "cancel_orders": "True", 110 | "order_mode": "Both", 111 | "take_profit_percent": "1", 112 | "stop_loss_percent": "0.5" 113 | } 114 | ``` 115 | 116 | 117 | 118 | --- 119 | | Constant |Settings Keys | 120 | |--|--| 121 | |key| unique key that protects your webhook server| 122 | |exchange | bybit, binacne-futures | 123 | |symbol | Exchange Specific ** See Below for more | 124 | |side|Buy or Sell | 125 | |type | Market or Limit | 126 | |order_mode| Both(Stop Loss & Take Profit Orders Used), Profit ( Omly Take Profit Orders), Stop (Only Stop Loss orders)| 127 | |qty| amount of base currency to buy | 128 | |price| ticker in quote currency | 129 | |close_position| True or False | 130 | |cancel_orders|True or False | 131 | |take_profit_percent| any float (0.5) | 132 | |stop_loss_Percent |and float (0.5) | 133 | 134 | 135 | #### ** SYMBOLS 136 | | EXCHANGE | SYMBOL EXAMPLE | 137 | |--|--| 138 | |BYBIT INVERSE| BTCUSD| 139 | |BYBIT PERP | BTCUSDT| 140 | |Binance Futures | BTC/USDT| 141 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import json 2 | from flask import Flask, render_template, request, jsonify 3 | from pybit import HTTP 4 | import time 5 | import ccxt 6 | from binanceFutures import Bot 7 | 8 | def validate_bybit_api_key(session): 9 | try: 10 | result = session.get_api_key_info() 11 | return True 12 | except Exception as e: 13 | print("Bybit API key validation failed:", str(e)) 14 | return False 15 | 16 | def validate_binance_api_key(exchange): 17 | try: 18 | result = exchange.fetch_balance() 19 | return True 20 | except Exception as e: 21 | print("Binance API key validation failed:", str(e)) 22 | return False 23 | 24 | app = Flask(__name__) 25 | 26 | # load config.json 27 | with open('config.json') as config_file: 28 | config = json.load(config_file) 29 | 30 | ############################################################################### 31 | # 32 | # This Section is for Exchange Validation 33 | # 34 | ############################################################################### 35 | 36 | use_bybit = False 37 | if 'BYBIT' in config['EXCHANGES']: 38 | if config['EXCHANGES']['BYBIT']['ENABLED']: 39 | print("Bybit is enabled!") 40 | use_bybit = True 41 | 42 | session = HTTP( 43 | endpoint='https://api.bybit.com', 44 | api_key=config['EXCHANGES']['BYBIT']['API_KEY'], 45 | api_secret=config['EXCHANGES']['BYBIT']['API_SECRET'] 46 | ) 47 | 48 | use_binance_futures = False 49 | if 'BINANCE-FUTURES' in config['EXCHANGES']: 50 | if config['EXCHANGES']['BINANCE-FUTURES']['ENABLED']: 51 | print("Binance is enabled!") 52 | use_binance_futures = True 53 | 54 | exchange = ccxt.binance({ 55 | 'apiKey': config['EXCHANGES']['BINANCE-FUTURES']['API_KEY'], 56 | 'secret': config['EXCHANGES']['BINANCE-FUTURES']['API_SECRET'], 57 | 'options': { 58 | 'defaultType': 'future', 59 | }, 60 | 'urls': { 61 | 'api': { 62 | 'public': 'https://testnet.binancefuture.com/fapi/v1', 63 | 'private': 'https://testnet.binancefuture.com/fapi/v1', 64 | }, } 65 | }) 66 | exchange.set_sandbox_mode(True) 67 | 68 | # Validate Bybit API key 69 | if use_bybit: 70 | if not validate_bybit_api_key(session): 71 | print("Invalid Bybit API key.") 72 | use_bybit = False 73 | 74 | # Validate Binance Futures API key 75 | if use_binance_futures: 76 | if not validate_binance_api_key(exchange): 77 | print("Invalid Binance Futures API key.") 78 | use_binance_futures = False 79 | 80 | @app.route('/') 81 | def index(): 82 | return {'message': 'Server is running!'} 83 | 84 | @app.route('/webhook', methods=['POST']) 85 | def webhook(): 86 | print("Hook Received!") 87 | data = json.loads(request.data) 88 | print(data) 89 | 90 | if int(data['key']) != config['KEY']: 91 | print("Invalid Key, Please Try Again!") 92 | return { 93 | "status": "error", 94 | "message": "Invalid Key, Please Try Again!" 95 | } 96 | 97 | ############################################################################## 98 | # Bybit 99 | ############################################################################## 100 | if data['exchange'] == 'bybit': 101 | 102 | if use_bybit: 103 | if data['close_position'] == 'True': 104 | print("Closing Position") 105 | session.close_position(symbol=data['symbol']) 106 | else: 107 | if 'cancel_orders' in data: 108 | print("Cancelling Order") 109 | session.cancel_all_active_orders(symbol=data['symbol']) 110 | if 'type' in data: 111 | print("Placing Order") 112 | if 'price' in data: 113 | price = data['price'] 114 | else: 115 | price = 0 116 | 117 | 118 | if data['order_mode'] == 'Both': 119 | take_profit_percent = float(data['take_profit_percent'])/100 120 | stop_loss_percent = float(data['stop_loss_percent'])/100 121 | current_price = session.latest_information_for_symbol(symbol=data['symbol'])['result'][0]['last_price'] 122 | if data['side'] == 'Buy': 123 | take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent), 2) 124 | stop_loss_price = round(float(current_price) - (float(current_price) * stop_loss_percent), 2) 125 | elif data['side'] == 'Sell': 126 | take_profit_price = round(float(current_price) - (float(current_price) * take_profit_percent), 2) 127 | stop_loss_price = round(float(current_price) + (float(current_price) * stop_loss_percent), 2) 128 | 129 | print("Take Profit Price: " + str(take_profit_price)) 130 | print("Stop Loss Price: " + str(stop_loss_price)) 131 | 132 | session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'], 133 | qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False, 134 | close_on_trigger=False, price=price, take_profit=take_profit_price, stop_loss=stop_loss_price) 135 | 136 | elif data['order_mode'] == 'Profit': 137 | take_profit_percent = float(data['take_profit_percent'])/100 138 | current_price = session.latest_information_for_symbol(symbol=data['symbol'])['result'][0]['last_price'] 139 | if data['side'] == 'Buy': 140 | take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent), 2) 141 | elif data['side'] == 'Sell': 142 | take_profit_price = round(float(current_price) - (float(current_price) * take_profit_percent), 2) 143 | 144 | print("Take Profit Price: " + str(take_profit_price)) 145 | session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'], 146 | qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False, 147 | close_on_trigger=False, price=price, take_profit=take_profit_price) 148 | elif data['order_mode'] == 'Stop': 149 | stop_loss_percent = float(data['stop_loss_percent'])/100 150 | current_price = session.latest_information_for_symbol(symbol=data['symbol'])['result'][0]['last_price'] 151 | if data['side'] == 'Buy': 152 | stop_loss_price = round(float(current_price) - (float(current_price) * stop_loss_percent), 2) 153 | elif data['side'] == 'Sell': 154 | stop_loss_price = round(float(current_price) + (float(current_price) * stop_loss_percent), 2) 155 | 156 | print("Stop Loss Price: " + str(stop_loss_price)) 157 | session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'], 158 | qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False, 159 | close_on_trigger=False, price=price, stop_loss=stop_loss_price) 160 | 161 | else: 162 | session.place_active_order(symbol=data['symbol'], order_type=data['type'], side=data['side'], 163 | qty=data['qty'], time_in_force="GoodTillCancel", reduce_only=False, 164 | close_on_trigger=False, price=price) 165 | 166 | return { 167 | "status": "success", 168 | "message": "Bybit Webhook Received!" 169 | } 170 | ############################################################################## 171 | # Binance Futures 172 | ############################################################################## 173 | if data['exchange'] == 'binance-futures': 174 | if use_binance_futures: 175 | bot = Bot() 176 | bot.run(data) 177 | return { 178 | "status": "success", 179 | "message": "Binance Futures Webhook Received!" 180 | } 181 | 182 | else: 183 | print("Invalid Exchange, Please Try Again!") 184 | return { 185 | "status": "error", 186 | "message": "Invalid Exchange, Please Try Again!" 187 | } 188 | 189 | if __name__ == '__main__': 190 | app.run(debug=False) 191 | 192 | 193 | -------------------------------------------------------------------------------- /binanceFutures.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | import ccxt 4 | import random 5 | import string 6 | 7 | with open('config.json') as config_file: 8 | config = json.load(config_file) 9 | 10 | 11 | if config['EXCHANGES']['binance-futures']['TESTNET']: 12 | exchange = ccxt.binance({ 13 | 'apiKey': config['EXCHANGES']['binance-futures']['API_KEY'], 14 | 'secret': config['EXCHANGES']['binance-futures']['API_SECRET'], 15 | 'options': { 16 | 'defaultType': 'future', 17 | }, 18 | 'urls': { 19 | 'api': { 20 | 'public': 'https://testnet.binancefuture.com/fapi/v1', 21 | 'private': 'https://testnet.binancefuture.com/fapi/v1', 22 | }, } 23 | }) 24 | exchange.set_sandbox_mode(True) 25 | else: 26 | exchange = ccxt.binance({ 27 | 'apiKey': config['EXCHANGES']['binance-futures']['API_KEY'], 28 | 'secret': config['EXCHANGES']['binance-futures']['API_SECRET'], 29 | 'options': { 30 | 'defaultType': 'future', 31 | }, 32 | 'urls': { 33 | 'api': { 34 | 'public': 'https://fapi.binance.com/fapi/v1', 35 | 'private': 'https://fapi.binance.com/fapi/v1', 36 | }, } 37 | }) 38 | 39 | class Bot: 40 | 41 | def __int__(self): 42 | pass 43 | 44 | def create_string(self): 45 | N = 7 46 | # using random.choices() 47 | # generating random strings 48 | res = ''.join(random.choices(string.ascii_uppercase + 49 | string.digits, k=N)) 50 | baseId = 'x-40PTWbMI' 51 | self.clientId = baseId + str(res) 52 | return 53 | 54 | def close_position(self, symbol): 55 | position = exchange.fetch_positions(symbol)[0]['info']['positionAmt'] 56 | self.create_string() 57 | params = { 58 | "newClientOrderId": self.clientId, 59 | 'reduceOnly': True 60 | } 61 | if float(position) > 0: 62 | print("Closing Long Position") 63 | exchange.create_order(symbol, 'Market', 'Sell', float(position), price=None, params=params) 64 | else: 65 | print("Closing Short Position") 66 | exchange.create_order(symbol, 'Market', 'Buy', -float(position), price=None, params=params) 67 | 68 | def set_risk(self, symbol, data, stop_loss, take_profit): 69 | position = exchange.fetch_positions(symbol) 70 | print(position) 71 | price = float(position[0]['info']['entryPrice']) 72 | size = abs(float(position[0]['info']['positionAmt'])) 73 | markPrice = float(exchange.fetch_ticker(data['symbol'])['last']) 74 | 75 | if data['order_mode'] == 'Both': 76 | if data['side'] == 'Buy': 77 | self.create_string() 78 | exchange.create_order(symbol, 'STOP_MARKET', 'Sell', size, params={ 79 | "newClientOrderId": self.clientId, 80 | 'reduceOnly': True, 81 | 'stopPrice': stop_loss, 82 | }) 83 | self.create_string() 84 | exchange.create_order(symbol, 'TAKE_PROFIT', 'Sell', size, params={ 85 | "newClientOrderId": self.clientId, 86 | 'reduceOnly': True, 87 | 'stopPrice': take_profit, 88 | }) 89 | else: 90 | self.create_string() 91 | exchange.create_order(symbol, 'STOP_MARKET', 'Buy', size, params={ 92 | "newClientOrderId": self.clientId, 93 | 'reduceOnly': True, 94 | 'stopPrice': stop_loss, 95 | }) 96 | self.create_string() 97 | exchange.create_order(symbol, 'TAKE_PROFIT', 'Buy', size, take_profit, params={ 98 | "newClientOrderId": self.clientId, 99 | 'reduceOnly': True, 100 | 'stopPrice': take_profit, 101 | }) 102 | 103 | elif data['order_mode'] == 'Profit': 104 | if data['side'] == 'Buy': 105 | self.create_string() 106 | exchange.create_order(symbol, 'TAKE_PROFIT', 'Sell', size, params={ 107 | "newClientOrderId": self.clientId, 108 | 'reduceOnly': True, 109 | 'stopPrice': take_profit, 110 | }) 111 | else: 112 | self.create_string() 113 | exchange.create_order(symbol, 'TAKE_PROFIT', 'Buy', size, take_profit, params={ 114 | "newClientOrderId": self.clientId, 115 | 'reduceOnly': True, 116 | 'stopPrice': take_profit, 117 | }) 118 | elif data['order_mode'] == 'Stop': 119 | if data['side'] == 'Buy': 120 | self.create_string() 121 | exchange.create_order(symbol, 'STOP_MARKET', 'Sell', size, params={ 122 | "newClientOrderId": self.clientId, 123 | 'reduceOnly': True, 124 | 'stopPrice': stop_loss, 125 | }) 126 | else: 127 | self.create_string() 128 | exchange.create_order(symbol, 'STOP_MARKET', 'Buy', size, params={ 129 | "newClientOrderId": self.clientId, 130 | 'reduceOnly': True, 131 | 'stopPrice': stop_loss, 132 | }) 133 | 134 | 135 | 136 | 137 | def run(self, data): 138 | print(data['close_position']) 139 | if data['close_position'] == 'True': 140 | print("Closing Position") 141 | self.close_position(symbol=data['symbol']) 142 | else: 143 | if 'cancel_orders' in data: 144 | print("Cancelling Order") 145 | exchange.cancel_all_orders(symbol=data['symbol']) 146 | if 'type' in data: 147 | print("Placing Order") 148 | if 'price' in data: 149 | price = data['price'] 150 | else: 151 | price = 0 152 | 153 | if data['order_mode'] == 'Both': 154 | take_profit_percent = float(data['take_profit_percent']) / 100 155 | stop_loss_percent = float(data['stop_loss_percent']) / 100 156 | current_price = exchange.fetch_ticker(data['symbol'])['last'] 157 | if data['side'] == 'Buy': 158 | take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent), 159 | 2) 160 | stop_loss_price = round(float(current_price) - (float(current_price) * stop_loss_percent), 2) 161 | elif data['side'] == 'Sell': 162 | take_profit_price = round(float(current_price) - (float(current_price) * take_profit_percent), 163 | 2) 164 | stop_loss_price = round(float(current_price) + (float(current_price) * stop_loss_percent), 2) 165 | 166 | print("Take Profit Price: " + str(take_profit_price)) 167 | print("Stop Loss Price: " + str(stop_loss_price)) 168 | 169 | self.create_string() 170 | params = { 171 | "newClientOrderId": self.clientId, 172 | 'reduceOnly': False 173 | } 174 | if data['type'] == 'Limit': 175 | exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']), 176 | price=float(price), params=params) 177 | else: 178 | exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']), 179 | params=params) 180 | 181 | self.set_risk(data['symbol'], data, stop_loss_price, take_profit_price) 182 | 183 | 184 | elif data['order_mode'] == 'Profit': 185 | take_profit_percent = float(data['take_profit_percent']) / 100 186 | current_price = exchange.fetch_ticker(data['symbol'])['last'] 187 | 188 | if data['side'] == 'Buy': 189 | take_profit_price = round(float(current_price) + (float(current_price) * take_profit_percent), 190 | 2) 191 | elif data['side'] == 'Sell': 192 | take_profit_price = round(float(current_price) - (float(current_price) * take_profit_percent), 193 | 2) 194 | 195 | print("Take Profit Price: " + str(take_profit_price)) 196 | 197 | self.create_string() 198 | params = { 199 | "newClientOrderId": self.clientId, 200 | 'reduceOnly': False 201 | } 202 | 203 | if data['type'] == 'Limit': 204 | exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']), 205 | price=float(price), params=params) 206 | else: 207 | exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']), 208 | params=params) 209 | 210 | self.set_risk(data['symbol'], data, 0, take_profit_price) 211 | 212 | 213 | elif data['order_mode'] == 'Stop': 214 | stop_loss_percent = float(data['stop_loss_percent']) / 100 215 | current_price = exchange.fetch_ticker(data['symbol'])['last'] 216 | 217 | if data['side'] == 'Buy': 218 | stop_loss_price = round(float(current_price) - (float(current_price) * stop_loss_percent), 2) 219 | elif data['side'] == 'Sell': 220 | stop_loss_price = round(float(current_price) + (float(current_price) * stop_loss_percent), 2) 221 | 222 | print("Stop Loss Price: " + str(stop_loss_price)) 223 | 224 | self.create_string() 225 | params = { 226 | "newClientOrderId": self.clientId, 227 | 'reduceOnly': False 228 | } 229 | 230 | if data['type'] == 'Limit': 231 | exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']), 232 | price=float(price), params=params) 233 | else: 234 | exchange.create_order(data['symbol'], data['type'], data['side'], float(data['qty']), 235 | params=params) 236 | 237 | self.set_risk(data['symbol'], data, stop_loss_price, 0) 238 | 239 | else: 240 | return { 241 | 'status': 'error' 242 | } 243 | --------------------------------------------------------------------------------