![]() |
API Problems!!! - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: API Problems!!! (/thread-42393.html) |
API Problems!!! - Dronemaster278 - Jun-29-2024 Hi! I am relatively nw to python, but i know a decent bit of C++ and HTML. However, this is my first time using API protocols. I am attempting to run a simple bot that buys a currency (DOGE) with another courrency (USDT) when the price culminatively drops more than 0.5%. I have code Here that shows how it should work. import requests import time from termcolor import colored # Initialize the bot's assets usd_balance = 100.0 doge_balance = 100.0 initial_price = None cumulative_change = 0.0 price_dip_threshold = -3.0 price_recovery_threshold = 1.0 in_dip_recovery_mode = False lowest_price_during_dip = None # Define the API endpoint and headers api_url = "https://api.coingecko.com/api/v3/simple/price?ids=dogecoin&vs_currencies=usd" # Configurable trade trigger thresholds gain_threshold = 0.3 loss_threshold = -0.3 def get_live_price(): try: response = requests.get(api_url) response.raise_for_status() data = response.json() return data['dogecoin']['usd'] except requests.exceptions.RequestException as e: print(colored(f"Error fetching live price: {e}", 'red')) return None def trade(direction, amount): global usd_balance, doge_balance current_price = get_live_price() if direction == 'sell': usd_earned = amount * current_price doge_balance -= amount usd_balance += usd_earned print(colored(f"Sold {amount} DOGE for {usd_earned:.2f} USD", 'green')) elif direction == 'buy': doge_bought = amount / current_price usd_balance -= amount doge_balance += doge_bought print(colored(f"Bought {doge_bought:.2f} DOGE for {amount} USD", 'green')) def report_change(old_price, new_price): global cumulative_change, in_dip_recovery_mode, lowest_price_during_dip change = (new_price - old_price) / old_price * 100 cumulative_change += change if change >= 0: print(colored(f"Price change: {change:.2f}% | Cumulative change: {cumulative_change:.2f}%", 'green')) else: print(colored(f"Price change: {change:.2f}% | Cumulative change: {cumulative_change:.2f}%", 'red')) print(f"New Price: {new_price} USD") if in_dip_recovery_mode: if new_price < lowest_price_during_dip: lowest_price_during_dip = new_price if (new_price - lowest_price_during_dip) / lowest_price_during_dip * 100 >= price_recovery_threshold: in_dip_recovery_mode = False print(colored("Exited dip recovery mode.", 'green')) else: if cumulative_change <= price_dip_threshold: in_dip_recovery_mode = True lowest_price_during_dip = new_price print(colored("Entered dip recovery mode.", 'red')) def calculate_total_value(current_price): return usd_balance + (doge_balance * current_price) def calculate_percentage_change(initial_value, current_value): return (current_value - initial_value) / initial_value * 100 # Start trading loop print("Fetching initial price...") initial_price = get_live_price() if initial_price is not None: print(f"Initial DOGE Price: {initial_price} USD") print(f"Starting Balances: {usd_balance} USD, {doge_balance} DOGE") else: print("Failed to fetch initial price. Exiting...") exit(1) previous_price = initial_price initial_total_value = calculate_total_value(initial_price) # Capture the initial total value while True: current_price = get_live_price() if current_price is None: time.sleep(30) continue if current_price != previous_price: report_change(previous_price, current_price) previous_price = current_price if not in_dip_recovery_mode: if cumulative_change >= gain_threshold: trade('sell', min(doge_balance / 2, doge_balance)) cumulative_change = 0.0 elif cumulative_change <= loss_threshold: trade('buy', min(usd_balance / 2, usd_balance)) cumulative_change = 0.0 total_value = calculate_total_value(current_price) percentage_change = calculate_percentage_change(initial_total_value, total_value) if percentage_change >= 0: print(colored(f"Total Value in USD: {total_value:.2f} ({percentage_change:.2f}%)", 'green')) else: print(colored(f"Total Value in USD: {total_value:.2f} ({percentage_change:.2f}%)", 'red')) print(f"USD Balance: {usd_balance:.2f} | DOGE Balance: {doge_balance:.2f}") # Wait for some time before checking the price again time.sleep(30) # 30 seconds intervalHere is the code that gives me this error whenever i attempt to buy DOGE. import time import requests import hmac import hashlib from datetime import datetime import pytz API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' API_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' BASE_URL = 'https://api.nonkyc.io' TOKEN_SYMBOL = 'DOGE_USDT' START_INVESTMENT = 10 TRADE_FEE = 0.002 PRICE_CHECK_INTERVAL = 20 PROFIT_MARGIN = 0.005 last_price = None current_investment = START_INVESTMENT initial_investment = START_INVESTMENT cumulative_gains = 0 def create_signature(secret, message): return hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest() def get_current_price(): try: response = requests.get(f'{BASE_URL}/api/v2/market/getbysymbol/{TOKEN_SYMBOL}') response.raise_for_status() data = response.json() return float(data['lastPrice']) except requests.exceptions.RequestException as e: print(f"{datetime.now(pytz.UTC)} - Error fetching price: {e}") return None def place_buy_order(quantity, price): try: endpoint = '/api/v2/createorder' timestamp = int(time.time() * 1000) params = { 'symbol': TOKEN_SYMBOL, 'side': 'BUY', 'type': 'LIMIT', 'timeInForce': 'GTC', 'quantity': quantity, 'price': price, 'timestamp': timestamp } query_string = '&'.join([f'{k}={v}' for k, v in sorted(params.items())]) signature = create_signature(API_SECRET, query_string) headers = { 'X-MBX-APIKEY': API_KEY } params['signature'] = signature response = requests.post(f'{BASE_URL}{endpoint}', headers=headers, params=params) response.raise_for_status() print(f"{datetime.now(pytz.UTC)} - Buy order placed successfully: {response.json()}") return True except requests.exceptions.RequestException as e: print(f"{datetime.now(pytz.UTC)} - Error placing buy order: {e}") return False def place_sell_order(quantity, price): try: endpoint = '/api/v2/createorder' timestamp = int(time.time() * 1000) params = { 'symbol': TOKEN_SYMBOL, 'side': 'SELL', 'type': 'LIMIT', 'timeInForce': 'GTC', 'quantity': quantity, 'price': price, 'timestamp': timestamp } query_string = '&'.join([f'{k}={v}' for k, v in sorted(params.items())]) signature = create_signature(API_SECRET, query_string) headers = { 'X-MBX-APIKEY': API_KEY } params['signature'] = signature response = requests.post(f'{BASE_URL}{endpoint}', headers=headers, params=params) response.raise_for_status() print(f"{datetime.now(pytz.UTC)} - Sell order placed successfully: {response.json()}") return True except requests.exceptions.RequestException as e: print(f"{datetime.now(pytz.UTC)} - Error placing sell order: {e}") return False def calculate_percentage_change(last_price, current_price): if last_price is None: return 0.0 percentage_change = ((current_price - last_price) / last_price) * 100 return percentage_change def format_percentage_change(percentage_change): if percentage_change > 0: return f"\033[92m+{percentage_change:.2f}%\033[0m" elif percentage_change < 0: return f"\033[91m{percentage_change:.2f}%\033[0m" else: return f"{percentage_change:.2f}%" def get_total_doge_balance(): try: endpoint = '/api/v2/balances' timestamp = int(time.time() * 1000) params = { 'timestamp': timestamp } query_string = '&'.join([f'{k}={v}' for k, v in sorted(params.items())]) signature = create_signature(API_SECRET, query_string) headers = { 'X-MBX-APIKEY': API_KEY } params['signature'] = signature response = requests.get(f'{BASE_URL}{endpoint}', headers=headers, params=params) response.raise_for_status() balances = response.json()['balances'] for balance in balances: if balance['asset'] == 'DOGE': return float(balance['free']) return 0.0 except requests.exceptions.RequestException as e: print(f"{datetime.now(pytz.UTC)} - Error fetching total DOGE balance: {e}") return 0.0 def main(): global last_price global current_investment global cumulative_gains total_doge_balance = get_total_doge_balance() print(f"{datetime.now(pytz.UTC)} - Total DOGE balance: {total_doge_balance:.4f}") print(f"{datetime.now(pytz.UTC)} - Starting investment: {START_INVESTMENT:.4f} DOGE") place_buy_order(0.0001, get_current_price()) while True: try: current_price = get_current_price() if current_price is not None: if last_price is None: last_price = current_price print(f"{datetime.now(pytz.UTC)} - Initial price set: ${last_price:.4f}") if current_price != last_price: percentage_change = calculate_percentage_change(last_price, current_price) formatted_change = format_percentage_change(percentage_change) log_message = f"Price: ${current_price:.4f} ({formatted_change})" print(f"{datetime.now(pytz.UTC)} - {log_message}") sell_threshold = last_price * (1 + PROFIT_MARGIN + TRADE_FEE) buy_threshold = last_price * (1 - PROFIT_MARGIN - TRADE_FEE) print(f"{datetime.now(pytz.UTC)} - Sell Threshold: ${sell_threshold:.4f}, Buy Threshold: ${buy_threshold:.4f}") if percentage_change > 0: cumulative_gains += percentage_change print(f"{datetime.now(pytz.UTC)} - Cumulative gains: {cumulative_gains:.2f}%") else: cumulative_gains = 0 if current_price >= sell_threshold or cumulative_gains >= (PROFIT_MARGIN + TRADE_FEE) * 100: if place_sell_order(current_investment, current_price): profit = (current_investment * current_price) - (initial_investment * last_price) profit_percentage = (profit / (initial_investment * last_price)) * 100 current_investment = 0 log_message = (f"Sold {START_INVESTMENT:.4f} DOGE at ${current_price:.4f} " f"for a profit of {profit:.4f} DOGE ({profit_percentage:+.2f}%)") print(f"{datetime.now(pytz.UTC)} - {log_message}") cumulative_gains = 0 elif current_price <= buy_threshold: if place_buy_order(START_INVESTMENT, current_price): current_investment = START_INVESTMENT profit = (initial_investment * last_price) - (current_investment * current_price) profit_percentage = (profit / (initial_investment * last_price)) * 100 log_message = (f"Bought {START_INVESTMENT:.4f} DOGE at ${current_price:.4f} " f"for a profit of {profit:.4f} DOGE ({profit_percentage:+.2f}%)") print(f"{datetime.now(pytz.UTC)} - {log_message}") last_price = current_price time.sleep(PRICE_CHECK_INTERVAL) except Exception as e: error_message = f"Error: {e}" print(f"{datetime.now(pytz.UTC)} - {error_message}") time.sleep(5) if __name__ == '__main__': main()This code give me this error. I also imported a library provided by the exchange (NonKYC.io). I have included it below. it is over 900 lines. I started trying to use this code to place a simple order for 0.001 DOGE, with this code, but that did not work.from nonkyc import NonKYCClient import asyncio TOKEN = 'DOGE_USDT' ACTION = 'sell' # Assuming 'sell' is the intended action async def main(): client = NonKYCClient() try: assets = await client.create_order( TOKEN, ACTION, 0.02, ) print(assets) finally: await client.close() # Ensuring the client session is closed asyncio.run(main())According to their API documentation, here is how the request should be formatted. { "symbol": "DOGE_USDT", "side": "buy", "type": "limit", "quantity": "0.002", "price": "0.12398", "strictValidate": false }Here is also a small snipet of the code from their website that is a shortcut to placing orders. async def create_order( self, symbol: str, side: str, quantity: str, price: Optional[str] = None, order_type: Optional[str] = None, user_provided_id: Optional[str] = None, strict_validate: Optional[str] = None, ): """Creates an order. Args: symbol: Market symbol, two tickers joined with a \"_\". For example \"XRG_LTC\". side: Order side, \"sell\" or \"buy\". quantity: Quantity of the base asset. price: Price in terms of the quote asset required for the limit order. order_type: "limit" or \"market\" ordeer type. user_provided_id: Optional user-defined ID. strict_validate: Strict validate amount and price precision without truncation. Setting true will return an error if your quantity/price exceeds the correct decimal places. Default false will truncate values to allowed number of decimal places. """This is my first time messing with APIs, and i am completely comfused. If anyone can help, it would be greatly appreciatted. RE: API Problems!!! - sawtooth500 - Jun-29-2024 First off... You posted to a public forum exposing your API keys for something that involves moving real money. Now anybody could theoretically go in and blow up your account. I'd get these changed immediately. Next a quick look at nonkyc.io shows me that they have two API types - REST and websockets. Both of these are standard API types. I'd recommend ditching library provided by the exchange - they tend to suck and may not always work well if you deploy to a server. Here is some code that I use to access a REST API from polygon.io - import requests import datetime import urllib3 import json from urllib3.exceptions import InsecureRequestWarning def poly_get_aggregates(stock_ticker, multiplier, timespan, from_date, to_date, api_key): url = f"https://api.polygon.io/v2/aggs/ticker/{stock_ticker}/range/{multiplier}/{timespan}/{from_date}/{to_date}?limit=50000" params = {'apiKey': api_key} if "api.polygon.io" in url: urllib3.disable_warnings(InsecureRequestWarning) #Suppress only the specific InsecureRequestWarning for api.polygon.io response = requests.get(url, params=params, verify=False) # Disable SSL verification if response.status_code == 200: return response.json() else: response.raise_for_status() if __name__ == "__main__": # Example usage stock_ticker = "TSLA" multiplier = 1 timespan = "hour" from_date = "2024-06-27" to_date = "2024-06-27" api_key = 'NOPENOTPOSTINGTHIS' try: aggregates = poly_get_aggregates(stock_ticker, multiplier, timespan, from_date, to_date, api_key) print(aggregates) print(json.dumps(aggregates, indent=4)) print(type(aggregates)) except requests.exceptions.HTTPError as e: print(f"Polygon Get Aggregates HTTP error occurred: {e}") except Exception as e: print(f"Polygon Get Aggregates general error occurred: {e}")https://nonkyc.io/api - Your REST API documentation is there. You should be able to change the endpoints from the above code to include your endpoints and it may work - you'd need to play around with it but at least this is a starting point. A caveat about the above code, for some reason when I connect to polygon's API code it can't ever verify their SSL certificate - so my code above is a bit of a hack that forces python to NOT verify the SSL cert, you may not have that issue. Polygon is just market data, not actual trading so I don't really care about a verified SSL connection to them. Another caveat, the nonkyc sample code you posted uses asyncio. If you're sending actual trades, I HIGHLY recommend using asyncio. The sample I posted above I just use to download historical market data, so I don't care about real time stuff there but if you're trading in real time asyncio is the way to go. You'll need to look at some tutorials as asynchronous programming is not easy to grasp at first, but with I/O operations in an API it's the way to go. When I get real time market data from polygon using their websockets API, I use asyncio for that. import asyncio import aiohttp import json #CHECK THESE EVERY DAY MODE = 'SIM' #LIVE or SIM REFRESH_TOKEN = 'NOPE' #THESE SHOULD NOT NORMALLY BE CHANGED #LIVE_ACCOUNT_ID = ''NOPE'' #1st live account LIVE_ACCOUNT_ID = ''NOPE''#2nd live account #SIM_ACCOUNT_ID = ''NOPE'' #1st sim account SIM_ACCOUNT_ID = ''NOPE'' #2nd sim account CLIENT_ID = ''NOPE'' CLIENT_SECRET = 'NOPE'' if MODE == 'LIVE': base_url = "https://api.tradestation.com" ACCOUNT_ID = LIVE_ACCOUNT_ID elif MODE == 'SIM': base_url = "https://sim-api.tradestation.com" ACCOUNT_ID = SIM_ACCOUNT_ID else: exit('ERROR: Live or sim not specified') if not REFRESH_TOKEN: REFRESH_TOKEN = input('Enter refresh token: ') async def get_access_token(): url = "https://signin.tradestation.com/oauth/token" payload = f'grant_type=refresh_token&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&refresh_token={REFRESH_TOKEN}' headers = { 'Content-Type': 'application/x-www-form-urlencoded' } async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, data=payload) as response: response_data = await response.json() return response_data['access_token'] async def place_order(session, access_token, symbol, quantity, ordertype, tradeaction, limitprice='error', tif={"Duration": "DAY"}, route='Intelligent'): url = base_url + "/v3/orderexecution/orders" payload = { "AccountID": ACCOUNT_ID, "Symbol": symbol, "Quantity": quantity, "OrderType": ordertype, "TradeAction": tradeaction, "LimitPrice": limitprice, "TimeInForce": tif, "Route": route } headers = { "Content-Type": "application/json", "Authorization": f'Bearer {access_token}' } async with session.post(url, json=payload, headers=headers) as response: response_text = await response.text() print(response_text) async def get_balances(): access_token = await get_access_token() # get a new access token url = base_url + f"/v3/brokerage/accounts/{ACCOUNT_ID}/balances" headers = { "Authorization": f'Bearer {access_token}' } async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: response_text = await response.text() print(response_text) async def stream_quotes(symbols): access_token = await get_access_token() # Get a new access token url = f"{base_url}/v3/marketdata/stream/quotes/{','.join(symbols)}" headers = {"Authorization": f"Bearer {access_token}"} async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: async for line in response.content: if line: print(json.dumps(json.loads(line.decode('utf-8')), indent=4)) # Run the async tasks symbols = ["AMD"] asyncio.run(stream_quotes(symbols))Above is REST API with asyncio that I use to communicate with my broker Tradestation for placing trades. You could possibly adapt it for your use case. RE: API Problems!!! - Dronemaster278 - Jun-29-2024 Thank you. For my API, it is to my extra account. only worht a few dollars. This might be a dumb question, but could you expand on what the difference between a REST API and a websocket API is? RE: API Problems!!! - sawtooth500 - Jun-29-2024 (Jun-29-2024, 07:07 PM)Dronemaster278 Wrote: Thank you. For my API, it is to my extra account. only worht a few dollars. This might be a dumb question, but could you expand on what the difference between a REST API and a websocket API is? https://aws.amazon.com/what-is/restful-api/ https://www.metered.ca/blog/the-websocket-api-and-protocol-explained/ |