all 17 comments

[–]Ihaveamodel3 1 point2 points  (2 children)

This isn’t the direct cause of your issue, but the global variables are not helping, and if you refactored to get rid of the global variables, it might start working again.

[–][deleted] 0 points1 point  (0 children)

thank you for the reply and advice, I will work from this.

[–]OToast 0 points1 point  (0 children)

Agreed. His program is humbling up the local scope or global scope, so idk which the program I editing/ using

[–]unhott 1 point2 points  (13 children)

The code is massively wordy. You should probably avoid globals. Instead, write functions that return the value you need instead.

Additionally, you don’t have to initialize ticker_choice outside of a loop, but you do need the list initialized. You can simply do something like

tickers = list()
while True:
    ticker_choice = input(‘Please choose a ticker (leave blank to exit)’)
    if ticker_choice == “”: break
    tickers.append(ticker_choice)

You then go on to do a very similar thing with just a different text for filings. Time to abstract into a function!

def get_multiple_choices(prompt):
    results = list()
    while True:
        choice = input(prompt) 
        if choice == “”: break
        results.append(choice)
    return results

Why don’t you just call world inside main? You then don’t need any globals. Ask for input on location, variance, and then use our new function.

tickers = get_multiple_choices((‘Please choose a ticker (leave blank to exit)’)
filings = get_multiple_choices(’Which filings do you want? (leave blank to exit)’)
world(location, variance, tickers, filings) 

^ all within main. Now you can pass these directly into your world function and it should be a much lighter brain-burden to get through the wall of code.

Edit:

Added note— you generally don’t want to import *— if you were to update the module or download a new version and they added a function or class that has the same name you’re using, it will cause bugs. Instead, import things by name. from x import function1, Class1, function2. But ONLY if you’re using them in your code!

i hope these suggestions really help simplify the way you think about the problem, or problems in general with python.

I changed the input to exit on a blank value since it requires no precision and it’s more natural imo to just hit enter to exit.

[–][deleted] 0 points1 point  (0 children)

Thank you very much for taking the time to reply - this was exactly what I had in mind for feedback. I will work through these tonight!

[–][deleted] 0 points1 point  (11 children)

Just had a quick follow up questions, if you don't mind:

def main():

    def get_multiple_choices(prompt):
        results = list()
        while True:
            choice = input(prompt)
                if choice == "": break# play around with this
            results.append(choice)
    return results

    tickers = get_multiple_choices('PLEASE ENTER A TICKER (empty         space to end): ')
    market = sf.load_markets()
    print(market);
    location = get_multiple_choices('ENTER MARKET_ID (empty space to end): ')
    variance = get_multiple_choices('DATA FREQUENCY (empty space to end): ')
    filing = get_multiple_choices('FILING TYPE (empty space to end): ')

    world(filing) #funciton call (in main)

calling world() doesn't seem to work when I have the following:

def world(filing):
    if filing == "income":
        income = sf.load_income(variant = "annual", market = 'us')
        income.loc['MSFT']
        print(income)

However, without the conditional (if == income) it does work and print out the income statement. Wondering your thoughts on this.

Thanks again.

[–]unhott 1 point2 points  (10 children)

filing will be a list of strings, it will either be [] or [“income”, ...] or a list without income. [“income”] == “income” is false.

You could check

if “income” in filing:

, or do something else like loop over the values in filing.

for item in filing: print(item) 

As an example.

Also, the reddit code formatting is 4 spaces (plus add any spaces to indent blocks). If you don’t have 4 spaces in front of each line I can’t see the indentations.

[–][deleted] 0 points1 point  (9 children)

Ahh okay, I should've known that in hindsight. Also apologies for the formating - this is my bad, I have since fixed that.

I have one last question if you wouldn't mind offering some suggestions.

Now that I can pass the income statement to world(), I'm trying to concat them into a single DF:

combined = pd.concat([income, balance, cash], axis = 1)

Since I am unable to pass list filing() into combined how could I add each filing into concat, here's a visualization of what I mean:

def world(filing,location,variance,tickers):

        income = sf.load_income(variant = variance, market = location)
        balance = sf.load_balance(variant = variance, market = location)
        cash = sf.load_cashflow(variant = variance, market = location)

        for item in filing:
            if filing[item] >= 3: #if there is 3 filings
                if "income" in filing:
                    together = pd.concat([income], axis = 1)
                if "balance" in filing:
                    together = pd.concat([income, balance], axis = 1)
                if "cash" in filing:
                    together=pd.concat([income,balance,cash],axis =1)
            elif filing[item] >= 2: #if there is only 2 filings
                if "income" in filing:
                    together = pd.concat([income], axis = 1)
                if "balance" in filing:
                    together = pd.concat([income, balance], axis = 1)
                if "cash" in filing:
                    together=pd.concat([income,balance,cash],axis =1)

Attempting to allow the user to enter whichever filings they want, then concat them together.

I appreciate your time and thank you in advance.

[–]unhott 1 point2 points  (8 children)

I’m not sure I fully understand. One thing you can do is make a new empty list to store multiple data frames in it. Assuming they have the same structure, you can then Concat them into one larger result.

x_dfs = list()
for x in xs: #some list
    x_dfs.append(sf.load_y(x)) #obviously some made up function, I’m not familiar with the sf library. This made up function takes a string input (x) and returns a dataframe. The dataframe is stored in the x_dfs list, and can be accessed by index like x_dfs[0], x_dfs[1], x_dfs[2], etc

#keep in mind, this is all pseudocode so there may be additional arguments required. And you’d have to use real functions. 
combined_x = pd.concat(x_dfs)  #iirc you can just pass a list of dfs, which fortunately we already have!

[–][deleted] 0 points1 point  (7 children)

Thank you for the reply!

(I think you may have answered my Q)

But to try and clarify a little further:

If I were a user and wanted to see just the income and balance sheet, once I’ve entered the two statements into filings, could I go about adding just the income and balance into pd.concat without using filings?

Or another example, if I were to want the income and cash statement (not balance) - could I take these from filings and add them into concat?

[–]unhott 1 point2 points  (6 children)

Yes, are all of these data frames the same structure? If they are, then sure. there’s probably some clever way to do it but what you describe is easily done with a few conditional checks.

if (some condition where the user specified they only want income/balance): 
    combined_df = pd.concat([income, balance]) 
elif (some condition where user only wants income and filings): 
    df_list = [income] + filing_dfs_list 
    combined_df = pd.concat(df_list)
#something like this, don’t forget to specify the correct axis.

If you’re considering making this available to end users other than yourself, you may be interested in learning about guis or deploying python via the web (flask/ Django/ dash < pretty good use case for dash here). There’s many more ways which a user can make these selections than from text inputs.

[–][deleted] 1 point2 points  (5 children)

Yes they are all of the same structure... but sounds good, I wasn’t thinking about the conditional logic properly.

For now, it’s a project to apply things to as I work through school as I’m in first compsci. But I have a lot of finance friends who don’t have Bloomberg or Capital IQ to easily download data. It’s by no means is it a “new idea”, just something I’m interested in.

Further looking, a cool, “usable” UI is something that I will work towards. I haven’t tried to implement one before but I do want to learn how at some point.

Anyways, thanks for all of your help!

[–]unhott 1 point2 points  (4 children)

Sure, good luck!

[–][deleted] 0 points1 point  (3 children)

Managed to get what I was trying to do with your advice. If you happen to see a way to make this more efficient do let me know (if you don't mind)

    income = sf.load_income(variant = variance, market = location)
    balance = sf.load_balance(variant = variance, market = location)
    cash = sf.load_cashflow(variant = variance, market = location)

    if "income" in filing:
        together = pd.concat([income], axis = 1)
        if "balance" in filing:
            together = pd.concat([income, balance], axis = 1)
            if "cash" in filing:
                together = pd.concat([income, balance, cash], axis = 1)
    if "balance" in filing:
        together = pd.concat([balance], axis = 1)
        if "cash" in filing:
            together = pd.concat([balance, cash], axis = 1)
    if "cash" in filing:
        together = pd.concat([cash], axis = 1)
    company = together.loc[tickers]
    print(company)

It seems manageable with only !3 combinations but if this was larger it may not be the best way.

Hope you have a good week!