I tried to do API trading in Kucoin. I developed a bot that is finding the trading opportunities well, while I encountered problems in making new orders. Pls check the code and help me to make it functional.
The code was edited in accordance with the comment of Lev Levitsky
is as follows:
import json
import urllib
import requests
import base64
import hmac
import hashlib
api_key = 'api_key'
api_secret = 'api_secret'
api_passphrase = 'api_passphrase'
base_uri = 'https://api-futures.kucoin.com'
endpoint = '/api/v1/orders?symbol=MATICUSDTM'
method = 'POST'
x= {}
x["symbol"] = "MATICUSDTM"
x["signal_type"] = "SHORT"
x["leverage"] = 5
x["exchange"] = "Kucoin"
x["entrance_price"] = 2.1000
x["trading_size"] = 150
x["tp1"] = 2.08
x["sl1"] = 2.12
all_futures_signals = list()
all_futures_signals.append(x)
def get_headers(method, endpoint, api_key, api_passphrase,body):
api_secret = ''
now = int(time.time() * 1000)
str_to_sign = str(now) + method + endpoint + str(body)
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
passphrase = base64.b64encode(hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
return {'KC-API-KEY': api_key,
'KC-API-KEY-VERSION': '2',
'KC-API-PASSPHRASE': passphrase,
'KC-API-SIGN': signature,
'KC-API-TIMESTAMP': str(now)}
body = {
"clientOid" : "",
"reduceOnly" : False, # A mark to reduce the position size only
"closeOrder" : False, # If closeOrder is set to TRUE, the system will close the position and the position size will become 0. Side, Size and Leverage fields can be left empty and the system will determine the side and size automatically.
"forceHold" : False, # The system will forcely freeze certain amount of funds for this order, including orders whose direction is opposite to the current positions. This feature is to ensure that the order won’t be canceled by the matching engine in such a circumstance that not enough funds are frozen for the order.
"hidden" : False, # A hidden order will enter but not display on the orderbook.
"iceberg" : False, # When placing an iceberg order, you need to set the visible size. The minimum visible size is 1/20 of the order size. The minimum visible size shall be greater than the minimum order size, or an error will occur.
"visibleSize" : 0, # When placing an iceberg order, you need to set the visible size. The minimum visible size is 1/20 of the order size. The minimum visible size shall be greater than the minimum order size, or an error will occur.
"leverage" : x["leverage"],
"postOnly" : False, # The post-only flag ensures that the trader always pays the maker fee and provides liquidity to the order book.
"price" : 2.1000, # The price specified must be a multiple number of the contract tickSize,
"remark" : "remark",
"side" : "buy",# sell/buy
"size" : x["trading_size"], # The size must be no less than the lotSize for the contract and no larger than the maxOrderQty.
"stop" : "", # down/up
"stopPrice" : "",
"stopPriceType": "", # TP/MP/IP: TP for trade price, MP for mark price, and IP for index price
"symbol" : x["symbol"],
"timeInForce" : "", # GTC/IOC: Good Till Canceled GTC and Immediate Or Cancel IOC.
"type" : "limit", # limit/market
}
headers = get_headers(method, endpoint, api_key, api_passphrase, body)
x["opening_response"] = requests.post( base_uri + endpoint, body, headers=headers).json()
print(x["opening_response"])
I receive this error: {'code': '400005', 'msg': 'Invalid KC-API-SIGN'}
All inputs are correct. I think there is a problem with the code.
Best Regards
Javad
I think the problem is your endpoint variable. I believe you should not add the symbol to endpoint, when you are trying to add a new order. Remove it from endpoint and pass the symbol in body object. The other thing is that I think you do not need to pass empty strings to optional fields in body object. I am not sure about this but I think you should remove them from body object. It is a signing problem, therefore you have to check 4 variables: timestamp, method, endpoint and body. I hope this works.
have you considered using ccxt? It makes dealing with lower level API stuff like this somewhat easier.
Given that it's singling out the signature as being invalid, but not saying any headers are missing, it could mean that the signature for str_to_sign variable is wrong?
Let's look at it:
api_secret = ''
now = int(time.time() * 1000)
str_to_sign = str(now) + method + endpoint + str(body)
From the looks of it, your api_secret is just an empty string, so the resulting signature won't be correct.
so, a couple of lines down when you make the signature:
signature = base64.b64encode(hmac.new(api_secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
Even though api_secret is given a value in the higher scope, it's overridden by this local variable which is an empty string.
If your api_secret were actually an empty string, then your code would produce the correct signature, but it's not so it isn't
So, If you give it as a param to your get_headers function ie.
def get_headers(method, endpoint, api_key, api_passphrase, api_secret, body):
And delete the first line api_secret = ''
Then maybe it will work?
If it doesn't work, then it's a different problem. (eg. if you had actually put your API key in there and just redacted it before posting). I don't know since I haven't tried running your code.
PS: To Edelweiss: Grüzi aus Berner Oberland!
According to a comment of edelweiss, an easier way is using the client of Kucoin API. It is here.
First, I installed the client using this code.
!pip install kucoin-futures-python
Then, I opened a position by this code:
from kucoin_futures.client import Trade
client = Trade(key='api_key', secret='api_secret', passphrase='api_passphrase', is_sandbox=False, url='')
order_id = client.create_limit_order(symbol, side, lever, size, price, clientOid='', **kwargs)
Related
new to python and API.
i have list of values like below
typeid=['1','12','32','1000','9']
I have to pass this value as parameter in API request, so that it would take one typeid at a time and append the json. code i have following but not sure how it will move from one value to other?
# activity type id store as following in other .py file typeid=['1','12','32','1000','9']
#importing the file in main program file.
From typeid list import activitytypeids
act1 = requests.get(host + '/rest/v1/activities.json',
params={
'activityTypeIds': activitytypeids[0]
}).text
json_obj = json.loads(act1)
results.append(json_obj)
more_result = json_obj['moreResult']
while True:
act1 = requests.get(host + '/rest/v1/activities.json',
params={
'activityTypeIds': activitytypeids[0]
}).text
json_obj = json.loads(act1)
results.append(json_obj)
more_result =json(results['moreResult'])
if not more_result:
break
How do I pass the activity's in request param one by one, so that get the result of all type ids.
take your code to get one id and put it in a function that accepts an activity_id, and change all activitytypeids[0] to just be activity_id
From typeid list import activitytypeids
def get_activity_id(activity_id):
act1 = requests.get(host + '/rest/v1/activities.json',
params={
'activityTypeIds': activity_id
}).text
return act1.json()
then you can just iterate over your list
results = [get_activity_id(id) for id in activitytypeids]
that said it seems very surprising that a variable named activityTypeIds only accepts one id ... i would very much expect this to be able to accept a list based on nothing more than the variable name
So I've queried the location_view resource using the code shown below. I've tried something similar using the geographic_view, but it also leads to the same problem. This problem is that metrics like average_cost or average_cpc are ~2800000. Now this obviously can't be correct. I was wondering if anyone has had a similar problem or if maybe, the actual value is multiplied by a factor of 1M or something
from google.ads.googleads.client import GoogleAdsClient
credentials = {
"developer_token": "xx",
"refresh_token": "xx",
"client_id":"xx",
"client_secret": "xx"}
client = GoogleAdsClient.load_from_dict(credentials)
query = """
SELECT location_view.resource_name, segments.date, metrics.average_cost, metrics.average_cpc, metrics.clicks, metrics.conversions, metrics.cost_micros, metrics.cost_per_conversion, metrics.impressions, metrics.interactions, metrics.interaction_rate, campaign.id, campaign.name, campaign.end_date, campaign.start_date FROM location_view WHERE segments.date DURING LAST_30_DAYS"""
ga_service = client.get_service("GoogleAdsService")
search_request = client.get_type("SearchGoogleAdsStreamRequest")
search_request.customer_id = "xx"
search_request.query = query
test = []
response = ga_service.search_stream(search_request)
for batch in response:
for row in batch.results:
test.append(row)
Yes, this is expected behavior. The cost metrics are micros, so need to be divided by 1,000,000. There's more detail on a similar thread on the API forum: https://groups.google.com/g/adwords-api/c/K4ux3hmlego?pli=1
I am using microsoft graph api to pull my emails in python and return them as a json object. There is a limitation that it only returns 12 emails. The code is:
def get_calendar_events(token):
graph_client = OAuth2Session(token=token)
# Configure query parameters to
# modify the results
query_params = {
#'$select': 'subject,organizer,start,end,location',
#'$orderby': 'createdDateTime DESC'
'$select': 'sender, subject',
'$skip': 0,
'$count': 'true'
}
# Send GET to /me/events
events = graph_client.get('{0}/me/messages'.format(graph_url), params=query_params)
events = events.json()
# Return the JSON result
return events
The response I get are twelve emails with subject and sender, and total count of my email.
Now I want iterate over emails changing the skip in query_params to get the next 12. Any method of how to iterate it using loops or recursion.
I'm thinking something along the lines of this:
def get_calendar_events(token):
graph_client = OAuth2Session(token=token)
# Configure query parameters to
# modify the results
json_list = []
ct = 0
while True:
query_params = {
#'$select': 'subject,organizer,start,end,location',
#'$orderby': 'createdDateTime DESC'
'$select': 'sender, subject',
'$skip': ct,
'$count': 'true'
}
# Send GET to /me/events
events = graph_client.get('{0}/me/messages'.format(graph_url), params=query_params)
events = events.json()
json_list.append(events)
ct += 12
# Return the JSON result
return json_list
May require some tweaking but essentially you're adding 12 to the offset each time as long as it doesn't return an error. Then it appends the json to a list and returns that.
If you know how many emails you have, you could also batch it that way.
I make a request to my ES in Python but I can only get 10,000 data. I will need to recover many more ( several hundred thousand).
I've modified the "size" variable but it can't go over 10.000
res_cpe = es.search(index=cpe_index, doc_type="entries", body = {
'size' : 10000,
'query': {
'match_all' : {}
}
})
I would like to have all entries in my "res_cpe" variable
You should try to use Scroll API which should help you to retrieve large numbers of results (or even all results, like in your case).
This functionality is similar to cursors from a traditional databases.
All you need to do, is to add scroll param to your request in Python client. Minimum viable example could look like this:
page = es.search(
index = 'yourIndex',
doc_type = 'yourType',
scroll = '2m',
search_type = 'query_then_fetch',
size = 1000,
body = {
//Your query's body
})
sid = page['_scroll_id']
scroll_size = page['hits']['total']
//Start scrolling
while (scroll_size > 0):
print "Scrolling..."
page = es.scroll(scroll_id = sid, scroll = '2m')
//Update the scroll ID
sid = page['_scroll_id']
//Get the number of results that we returned in the last scroll
scroll_size = len(page['hits']['hits'])
print "scroll size: " + str(scroll_size)
//Do something with the obtained page
Example taken from here - https://gist.github.com/drorata/146ce50807d16fd4a6aa
Python client docs reference - https://elasticsearch-py.readthedocs.io/en/master/api.html
I'm trying to duplicate some subscription Plans in my Stripe account using the Python SDK, so that I can update the plan prices (plans are immutable). I can successfully list all plans, so authentication is not an issue.:
import stripe
stripe.api_key = 'sk_test_...'
start_id = None
while True:
if start_id:
resp = stripe.Plan.list(starting_after=start_id)
else:
resp = stripe.Plan.list()
plans = resp['data']
if len(plans) == 0: break
start_id = plans[-1]['id']
for plan in plans:
new_amount = get_new_plan_amount(plan['id'], plan['name'])
new_plan = {
"id": "%s-v2" % plan["id"],
"name": "%s V2" % plan["name"],
"amount": new_amount,
"interval": plan["interval"],
"currency": plan["currency"],
}
if plan['interval_count']:
new_plan["interval_count"] = plan['interval_count']
if plan['metadata']:
new_plan["metadata"] = plan['metadata']
if plan['statement_descriptor']:
new_plan["statement_descriptor"] = plan['statement_descriptor']
stripe.Plan.create(new_plan) ### error
When I try to update a plan I get the following error:
Stripe.error.AuthenticationError: Invalid API Key provided: "{'****': *'*********** ', '********': *'*****', '********_*****': *, '********': '', '******': *****, '**': *'*******-v2'}". This key contains at least one space. Please delete the spaces and try again.
I don't get it. Which field is it that contains a space? I've checked the id field (which it seems to be suggesting) but there are no spaces in that field.
I'm using Python 2.7 and version 2013-08-13 of the Stripe API.
You need to unpack the dictionary containing your parameters when creating the plan:
stripe.Plan.create(**new_plan)
Additionally, you don't need to manage pagination parameters yourself. The Python library can do it for you using auto-pagination:
plans = stripe.Plan.list()
for plan in plans.auto_paging_iter():
# do something with plan