I've created the following code, that pulls Cryptocurrency prices from the CoinGecko api and parses the bits I need in JSON
btc = requests.get("https://api.coingecko.com/api/v3/coins/bitcoin")
btc.raise_for_status()
jsonResponse = btc.json() # print(response.json()) for debug
btc_marketcap=(jsonResponse["market_data"]["market_cap"]["usd"])
This works fine, except I then need to duplicate the above 4 lines for every currency which is getting long/messy & repetitive.
After researching I felt an approach was to store the coins in an array, and loop through the array replacing bitcoin in the above example with each item from the array.
symbols = ["bitcoin", "ethereum", "sushi", "uniswap"]
for x in symbols:
print(x)
This works as expected, but I'm having issues substituting bitcoin/btc for x successfully.
Any pointers appreciated, and whether this is the best approach for what I am trying to achieve
Something like this could work. Basically, just put the repeated part inside a function and call it with the changing arguments (currency). The substitution of the currency can be done for example with f-strings:
def get_data(currency):
btc = requests.get(f"https://api.coingecko.com/api/v3/coins/{currency}")
btc.raise_for_status()
return btc.json()["market_data"]["market_cap"]["usd"]
for currency in ["bitcoin", "ethereum", "sushi", "uniswap"]:
print(get_data(currency))
Related
I am a beginner and I am trying to teach myself Python by using topics that are interesting to me and where I can at the same time challenge myself. I am currently struggling with a generic logical problem.
I would like to consume the CoinGecko API by using the following endpoint:
https://api.coingecko.com/api/v3/coins/bitcoin/market_chart?vs_currency=usd&days=max&interval=daily
I would like to replace "bitcoin" with a dynamic variable that refers to a list that I already have. (bitcoin, ethereum, fantom, avalanche-2)
Therefore I use the following code in combination with for i in list with a counter:
counter = 0
CoinDatabase = []
for i in CoinIDList:
if counter >2:
break
else:
r = requests.get (f"https://api.coingecko.com/api/v3/coins/{i}/market_chart?vs_currency=usd&days=max&interval=daily")
data = r.json()
prices = data["prices"]
market_caps = data["market_caps"]
total_volumes = data["total_volumes"]
for i in range (len(CoinDatabase)):
prices = data["prices"]
CoinDatabase.append(prices)
counter = counter+1
What is the smartest way to match the ID that is used in the "i" with the JSON response that I receive in every loop? Otherwise I get tons of JSONs without having the reference to what coin it belongs to.
My long term objective is to setup a small database with different values and maximum historical data for prices, market_caps, total_volumes, timestamp - just as a Python learning exercise.
Thanks in advance!
Im building a google sheet to keep track of stock prices for the stocks i own. I have an API running thats connected to Google Sheets and my own python application.
My google sheet looks like this
Stock | Previous close
AAPL | 316.73
NVDA | 348.71
SPOT | 191.00
i currently have the code running as follows.
import requests
import gspread
from oauth2client.service_account import ServiceAccountCredentials
sheet = client.open("Stock").sheet1
AAPL = sheet.cell(2,1).value
url = ('https://ca.finance.yahoo.com/quote/'+AAPL+'?p='+AAPL+'&.tsrc=fin-srch')
response = requests.get(url)
htmltext = response.text
splitlist = htmltext.split("Previous Close")
afterfirstsplit =splitlist[1].split("\">")[2]
aftersecondsplit = afterfirstsplit.split("</span>")
datavalue = aftersecondsplit[0]
sheet.update_cell(2,2,datavalue)
# this would update the value within my google sheet to the previous close price
For each individual stock, i would copy and paste, change the stock symbol, to find the value of the next quote.
I know theres a way to use FOR statements to automate this process. I tried that with the following but it wouldnt update as needed. I reached a wall at this point and would appreciate any help or insight on how i could automate this function.
tickers = {sheet.cell(2,1).value : [],
sheet.cell(3,1).value : [],
sheet.cell(4,1).value : [],
sheet.cell(5,1).value :[]}
for symbols in tickers:
url = ('https://ca.finance.yahoo.com/quote/'+symbols+'?p='+symbols+'&.tsrc=fin-srch')
response = requests.get(url)
htmltext = response.text
splitlist = htmltext.split("Previous Close")
afterfirstsplit =splitlist[1].split("\">")[2]
aftersecondsplit = afterfirstsplit.split("</span>")
datavalue = aftersecondsplit[0]
sheet.update.cell(2,1,datavalue)
print (datavalue)
Doing this gathers all the values of the current stock prices and it does import it into the excel file but only to one coordinate. I dont know how to increase the '1' within sheet.update.cell(2,1,datavalue), each time within the FOR statement. I believe that is the way to solve this, but if anyone has any other suggestions, im all ears.
In regards to answering this part of your question:
"I don't know how to increase the '1' within sheet.update.cell(2,1,datavalue), each time within the FOR statement."
This is how you increment a counter inside a for loop typically speaking:
counter = 1
for symbol in tickers:
#Your code
sheet.update.cell(2,counter,datavalue)
counter = counter+1
While counter variables are a very common pattern used in most programming language (see Akib Rhast's answer), the more pythonic way to do it is by using the enumerate builtin function:
for column, symbol in enumerate(tickers, start=1):
# do stuff
sheet.update.cell(2,column,datavalue)
what is enumerate?
As the documentation states, enumerate takes something that you can iterate on (like a list) and returns a tuple with the counter as the first element and the elements from the iterator as the second element:
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
list(enumerate(seasons, start=1))
# outputs [(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
It also has the advantage of doing so in a memory-efficient manner and is directly tied to your loop.
why is there a comma in my for loop?
This is just syntactic sugar in python that allows you to unpack a tuple or list:
alist = [1, 2, 3]
first, second, third = alist
print(third) # outputs 3
print(second) # outputs 2
print(first) # outputs 1
As enumerate returns a tuple, you are basically assigning each element on that tuple to a different variable at the same time.
So I have a good one. I'm trying to build two lists (ku_coins and bin_coins) of crypto tickers from two different exchanges, but I don't want to double up, so if it appears on both exchanges I want to remove it from ku_coins.
A slight complication occurs as Kucoin symbols come in as AION-BTC, while Binance symbols come in as AIONBTC, but it's no problem.
So firstly, I create the two lists of symbols, which runs fine, no problem. What I then try and do is loop through the Kucoin symbols and convert them to the Binance style symbol, so AIONBTC instead of AION-BTC. Then if it appears in the Binance list I want to remove it from the Kucoin list. However, it appears to randomly refuse to remove a handful of symbols that match the requirement. For example AION.
It removes the majority of doubled up symbols but in AIONs case for example it just won't delete it.
If I just do print(i) after this loop:
for i in ku_coins:
if str(i[:-4] + 'BTC') in bin_coins:
It will happily print AION-BTC as one of the symbols, as it fits the requirement perfectly. However, when I stick the ku_coins.remove(i) command in before printing, it suddenly decideds not to print AION suggesting it doesn't match the requirements. And it's doing my head in. Obviously the remove command is causing the problem, but I can't for the life of me figure out why. Any help really appreciated.
import requests
import json
ku_dict = json.loads(requests.get('https://api.kucoin.com/api/v1/market/allTickers').text)
ku_syms = ku_dict['data']['ticker']
ku_coins = []
for x in range(0, len(ku_syms)):
if ku_syms[x]['symbol'][-3:] == 'BTC':
ku_coins.append(ku_syms[x]['symbol'])
bin_syms = json.loads(requests.get('https://www.binance.com/api/v3/ticker/bookTicker').text)
bin_coins = []
for i in bin_syms:
if i['symbol'][-3:] == 'BTC':
bin_coins.append(i['symbol'])
ku_coins.sort()
bin_coins.sort()
for i in ku_coins:
if str(i[:-4] + 'BTC') in bin_coins:
ku_coins.remove(i)
#top bantz, #Fourier has already mentioned that you shouldn't modify a list you're iterating over. What you can do in this case is to create a copy of ku_coins first then iterate over that, and then remove the element from the original ku_coins that matches your if condition. See below:
ku_coins.sort()
bin_coins.sort()
# Create a copy
ku_coins_ = ku_coins[:]
# Then iterate over that copy
for i in ku_coins_:
if str(i[:-4] + 'BTC') in bin_coins:
ku_coins.remove(i)
How about modifying the code to:
while ku_coins:
i = ku_coins.pop()
if str(i[:-4] + 'BTC') in bin_coins:
pass
else:
# do something
the pop() method removes i from the ku_coins list
pop()
I must be missing something here since the computer doesn't joke around but this simple for loop is seemingly not giving me the desired output. Below is the code which uses aztro's API to grab today's horoscope for each of 12 zodiac signs and put them all in a list.
import requests
import json
zodiacSigns = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
for zodiacSign in zodiacSigns:
params = (('sign','{}'.format(zodiacSign)), ('day','today'))
output = json.loads(requests.post('https://aztro.sameerkumar.website/', params=params).text)
descriptions = []
descriptions.append(output['description'])
print(descriptions)
This code outputs the horoscope for only Pisces, the last element in the list above:
["You need to take work more seriously today -- it may be that you've got an opportunity coming up that shouldn't be missed. It's easier than usual for you to make career moves, so go for it!"]
As a reference, a sample output of this aztro's API for a single zodiac sign is:
{
"compatibility":" Virgo",
"date_range":"Jan 20 - Feb 18",
"current_date":"August 23, 2018",
"description":"Today requires a willingness to go deeper than usual -- maybe to explore the nuances of your primary relationship, maybe to really get to know that one client or maybe just reading between the lines.",
"lucky_time":" 10am",
"lucky_number":" 13",
"color":" Navy Blue",
"mood":" Thoughtful"
}
The desired output would be a list of horoscopes for all 12 zodiac signs. I can't seem to catch the issue here, so I'd appreciate input from more experienced eyes. Gracias!
The problem lies in the declaration of the descriptions variable, which at every iteration is initialized to be an empty list.
Just move it out from the loop, like so:
descriptions = []
for zodiacSign in zodiacSigns:
params = (('sign','{}'.format(zodiacSign)), ('day','today'))
output = json.loads(requests.post('https://aztro.sameerkumar.website/', params=params).text)
descriptions.append(output['description'])
The statement descriptions = [] should be out of the for loop. If it is in the for loop, it will be initiated (erased, in this case) every iteration.
The code below should work:
import requests
import json
zodiacSigns = ['Aries', 'Taurus', 'Gemini', 'Cancer', 'Leo', 'Virgo', 'Libra', 'Scorpio', 'Sagittarius', 'Capricorn', 'Aquarius', 'Pisces']
descriptions = []
for zodiacSign in zodiacSigns:
params = (('sign','{}'.format(zodiacSign)), ('day','today'))
output = json.loads(requests.post('https://aztro.sameerkumar.website/', params=params).text)
descriptions.append(output['description'])
print(descriptions)
I am writing a program to analyze some of our invoice data. Basically,I need to take an array containing each individual invoice we sent out over the past year & break it down into twelve arrays which contains the invoices for that month using the dateSeperate() function, so that monthly_transactions[0] returns Januaries transactions, monthly_transactions[1] returns Februaries & so forth.
I've managed to get it working so that dateSeperate returns monthly_transactions[0] as the january transactions. However, once all of the January data is entered, I attempt to append the monthly_transactions array using line 44. However, this just causes the program to break & become unrepsonsive. The code still executes & doesnt return an error, but Python becomes unresponsive & I have to force quite out of it.
I've been writing the the global array monthly_transactions. dateSeperate runs fine as long as I don't include the last else statement. If I do that, monthly_transactions[0] returns an array containing all of the january invoices. the issue arises in my last else statement, which when added, causes Python to freeze.
Can anyone help me shed any light on this?
I have written a program that defines all of the arrays I'm going to be using (yes I know global arrays aren't good. I'm a marketer trying to learn programming so any input you could give me on how to improve this would be much appreciated
import csv
line_items = []
monthly_transactions = []
accounts_seperated = []
Then I import all of my data and place it into the line_items array
def csv_dict_reader(file_obj):
global board_info
reader = csv.DictReader(file_obj, delimiter=',')
for line in reader:
item = []
item.append(line["company id"])
item.append(line["user id"])
item.append(line["Amount"])
item.append(line["Transaction Date"])
item.append(line["FIrst Transaction"])
line_items.append(item)
if __name__ == "__main__":
with open("ChurnTest.csv") as f_obj:
csv_dict_reader(f_obj)
#formats the transacation date data to make it more readable
def dateFormat():
for i in range(len(line_items)):
ddmmyyyy =(line_items[i][3])
yyyymmdd = ddmmyyyy[6:] + "-"+ ddmmyyyy[:2] + "-" + ddmmyyyy[3:5]
line_items[i][3] = yyyymmdd
#Takes the line_items array and splits it into new array monthly_tranactions, where each value holds one month of data
def dateSeperate():
for i in range(len(line_items)):
#if there are no values in the monthly transactions, add the first line item
if len(monthly_transactions) == 0:
test = []
test.append(line_items[i])
monthly_transactions.append(test)
# check to see if the line items year & month match a value already in the monthly_transaction array.
else:
for j in range(len(monthly_transactions)):
line_year = line_items[i][3][:2]
line_month = line_items[i][3][3:5]
array_year = monthly_transactions[j][0][3][:2]
array_month = monthly_transactions[j][0][3][3:5]
#print(line_year, array_year, line_month, array_month)
#If it does, add that line item to that month
if line_year == array_year and line_month == array_month:
monthly_transactions[j].append(line_items[i])
#Otherwise, create a new sub array for that month
else:
monthly_transactions.append(line_items[i])
dateFormat()
dateSeperate()
print(monthly_transactions)
I would really, really appreciate any thoughts or feedback you guys could give me on this code.
Based on the comments on the OP, your csv_dict_reader function seems to do exactly what you want it to do, at least inasmuch as it appends data from its argument csv file to the top-level variable line_items. You said yourself that if you print out line_items, it shows the data that you want.
"But appending doesn't work." I take it you mean that appending the line_items to monthly_transactions isn't being done. The reason for that is that you didn't tell the program to do it! The appending that you're talking about is done as part of your dateSeparate function, however you still need to call the function.
I'm not sure exactly how you want to use your dateFormat and dateSeparate functions, but in order to use them, you need to include them in the main function somehow as calls, i.e. dateFormat() and dateSeparate().
EDIT: You've created the potential for an endless loop in the last else: section, which extends monthly_transactions by 1 if the line/array year/month aren't equal. This is problematic because it's within the loop for j in range(len(monthly_transactions)):. This loop will never get to the end if the length of monthly_transactions is increased by 1 every time through.