I am trying to link a script to an excel file using xlwings that takes data from the sheet and queries skyscanners API to return flight prices. When I type dates in manually (yyyy-mm-dd), it works fine since it is a String. However, when I try to run the query by automatically loading the date from excel, it cannot work with excel's date format.
When I just return type(dept_date), I get the error: Unexpected Python Error: TypeError: must be a pywintypes time object (got type)"
When I try to convert dept_date to a string first and return that type, I get: Unexpected Python Error: TypeError: Objects of type 'type' can not be converted to a COM VARIANT.
For context, the API takes the yyyy-mm-dd format and when I print the querystring, excel automatically adds the "00:00:00" to the end of the date. I've tried subscripting [:9] to just pull the date but since it isn't a String, that doesn't work. I've tried casting to a string and doing that too with no luck. Any help is appreciated! I've included the whole function below just in case:
#xw.func
def airfare(trip_type, home_iata, dest_iata, dept_date, return_date=""):
""" Pass home IATA, destination IATA, departure/return dates (yyyy-mm-dd). Returns average of "best"
results. All params are strings. To account for last minute booking, if flight is < 500, result doubles.
If flight is 500+, it adds a 30% surcharge onto result. Trip type 1 = Round Trip; 0 = One-Way
"""
home_iata = str(home_iata)
dest_iata = str(dest_iata)
dept_date = str(dept_date)
# dept_date.strftime('%d-%m-%Y')
if trip_type == "0":
return_date = ""
url = "https://skyscanner44.p.rapidapi.com/search"
querystring = {"adults": "1",
"origin": home_iata,
"destination": dest_iata,
"departureDate": dept_date,
"returnDate": return_date,
"cabinClass": "economy",
"currency": "USD"}
headers = {
"X-RapidAPI-Key": "XXX",
"X-RapidAPI-Host": "skyscanner44.p.rapidapi.com"
}
# return querystring
# return type(dept_date)
response = requests.request("GET", url, verify=False, headers=headers, params=querystring).json()
best_flight = int(response["itineraries"]["buckets"][0]["items"][0]["price"]["raw"])
if best_flight < 500:
best_flight *= 2
else:
best_flight *= 1.3
return "$" + str(best_flight)
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
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)
In my app, when the user adds a document, I store the timestamp of the document creation.
My app calls an api written in Flask.
I store the timestamp in python with:
timestamp = firestore.SERVER_TIMESTAMP
The timestamp is stored in Firestore as:
When the user requests the document, I process the timestamp to be shown in a readable way with the following code:
def get_proper_timestamp(timestamp) -> str:
if not timestamp:
return None
date: datetime.date = timestamp.date()
day = str(date.day)
month = str(date.month)
year = str(date.year)
if len(month) == 1:
month = f"0{month}"
proper_date = f"{day} {month} {year}"
weekday: int = date.weekday()
proper_weekday: str = get_day_from_int(weekday)
time = timestamp.time()
hour = time.hour
minute = time.minute
temp = strptime(f"{hour}:{minute}", "%H:%M")
proper_time: str = strftime("%I:%M %p", temp)
return f"{proper_weekday}, {proper_date}.{proper_time}"
def get_day_from_int(integer: int) -> str:
mapper = {
0: "Mon",
1: "Tues",
2: "Wed",
3: "Thur",
4: "Fri",
5: "Sat",
6: "Sun",
}
return mapper[integer]
In Postman, this outputs:
My flutter code reads the timestamp in a straight-forward way:
List<DataCell> _buildCells(Map<String, dynamic> entry) {
String timestamp = entry["timestamp"];
print(timestamp);
return [
DataCell(Text(entry["timestamp"].toString())),
DataCell(Text(entry["amount"].toString())),
DataCell(Text(entry["after"].toString()))
];
}
This outputs:
This is four hours before. Which I think it means that I'm the UTF offset somewhere.
But why is Postman showing the date correctly?
I'd actually prefer flask to return the raw timestamp, but I couldn't deserialize it.
I read most the answers on SO on this issue, but nothing worked for me.
The value stored in Firestore is an internal structure, which is timezone agnostic (internally based on UTC).
The value you see in the Firestore console has been localized to your local timezone for your convenience, which is apparently UTC+4.
The value you get when fetching the time with Flutter is a Timestamp, also UTC-based and timezone agnostic. When you convert that with .toDate() (or the equivalent with millisecondsSinceEpoch), it becomes a traditional DateTime, which is internally in UTC, but carries a localtime offset, and normally displays itself as localtime. This is probably the value you are seeing as +4.
I'm trying to convert a working python program that retrieves information from a website with an api key to its R equivalent. Since I don't know much about httr or python it's a challenge. The python code is (somewhat abbreviated and with a dummy X-ApiKey)
url = 'https://api.clarivate.com/api/woslite'
query = 'ts=((land AND ocean AND climate AND change)) AND PY=2013-2019'
count = 100
firstRecord = 1
parameters = {'databaseId': 'WOK', 'usrQuery': query, 'count': count, 'firstRecord': firstRecord}
headers={'accept':'application/json','X-ApiKey':'********'}
response = requests.get(url,params=parameters, headers=headers)
My attempt at an R version is
library(httr)
wosliteKey <- Sys.getenv("wosliteKey")
firstRecord <- 1
count <- 100
url <- 'https://api.clarivate.com/api/woslite'
query <- 'ts=(land AND ocean AND climate AND change) AND PY=2013-2019'
r <- GET(url, query = list(api_key = wosliteKey, usrQuery = query, databaseId = 'WOK', count = count, firstRecord = firstRecord))
Running the above returns
Response [https://api.clarivate.com/api/woslite]
Date: 2019-05-09 22:50
Status: 401
Content-Type: application/json; charset=utf-8
Size: 41 B
status 401 means unauthorized access. The python code uses X-ApiKey rather than api_key. But I can't figure out a. what the difference is and b. how to put it into the query list.
With the help of the comments above I figured out how to make this work. The python version of httr GET looks like the following
response = requests.get(url,params=parameters, headers=headers)
For my problem, I have the following from the python program
parameters = {'databaseId': 'WOK', 'usrQuery': query, 'count': count, 'firstRecord': firstRecord}
headers={'accept':'application/json','X-ApiKey':'********'}
The equivalent with httr GET is
response <- httr::GET(url, httr::add_headers(accept = 'application/json', `X-APIKey` = wosliteKey), query = list(databaseId = 'WOK', usrQuery = query, count = count, firstRecord = firstRecord))
The python headers info is replaced by the add_headers function from httr. The python parameters info is added as a list in the query option.
I searched for a while, i found something looks working with your problem.
android package - R.attr nested class -- employing an api key
I need to loop through commits and get name, date, and messages info from
GitHub API.
https://api.github.com/repos/droptable461/Project-Project-Management/commits
I have many different things but I keep getting stuck at string indices must be integers error:
def git():
#name , date , message
#https://api.github.com/repos/droptable461/Project-Project-Management/commits
#commit { author { name and date
#commit { message
#with urlopen('https://api.github.com/repos/droptable461/Project Project-Management/commits') as response:
#source = response.read()
#data = json.loads(source)
#state = []
#for state in data['committer']:
#state.append(state['name'])
#print(state)
link = 'https://api.github.com/repos/droptable461/Project-Project-Management/events'
r = requests.get('https://api.github.com/repos/droptable461/Project-Project-Management/commits')
#print(r)
#one = r['commit']
#print(one)
for item in r.json():
for c in item['commit']['committer']:
print(c['name'],c['date'])
return 'suc'
Need to get person who did the commit, date and their message.
item['commit']['committer'] is a dictionary object, and therefore the line:
for c in item['commit']['committer']: is transiting dictionary keys.
Since you are calling [] on a string (the dictionary key), you are getting the error.
Instead that code should look more like:
def git():
link = 'https://api.github.com/repos/droptable461/Project-Project-Management/events'
r = requests.get('https://api.github.com/repos/droptable461/Project-Project-Management/commits')
for item in r.json():
for key in item['commit']['committer']:
print(item['commit']['committer']['name'])
print(item['commit']['committer']['date'])
print(item['commit']['message'])
return 'suc'