def click_transactions():
    transact = rs.get_bank_transfers()
    card = rs.get_card_transactions()

    # Get the deposits, withdrawals, debits, and reversal fees for your account
    dep = sum(
        float(x['amount']) for x in transact
        if (x['direction'] == 'deposit') and (x['state'] == 'completed'))
    withd = sum(
        float(x['amount']) for x in transact
        if (x['direction'] == 'withdraw') and (x['state'] == 'completed'))
    debit = sum(
        float(x['amount']['amount']) for x in card
        if (x['direction'] == 'debit' and (x['transaction_type'] == 'settled')
            ))
    reversal_fees = sum(
        float(x['fees']) for x in transact
        if (x['direction'] == 'deposit') and (x['state'] == 'reversed'))

    # Must convert to strings to be used properly in the text box
    converted_deposits = str(round(dep, 2))
    converted_withdrawals = str(round(withd, 2))
    converted_total = str(round(dep - withd - debit - reversal_fees, 2))
    transaction_text = "All in all you have deposited: " + converted_deposits + " USD " + "and Withdrawn: " \
                       + converted_withdrawals + " USD " + '\n' + \
                       "The total amount you have put into Robinhood is " + converted_total + " USD"
    print(transaction_text)

    # Print transactions in the actual text box
    label = tk.Label(root)
    label.pack()
    tab_title = tk.Tk()
    tab_title.title("Transactions")
    converted_deposits = str(round(dep, 2))
    converted_withdrawals = str(round(withd, 2))
    converted_total = str(round(dep - withd - debit - reversal_fees, 2))
    transaction_text = "All in all you have deposited: " + converted_deposits + " USD " + "and Withdrawn: " \
                       + converted_withdrawals + " USD " + '\n' + \
                       "The total amount you have put into Robinhood is " + converted_total + " USD"
    label = tk.Label(tab_title, text=transaction_text)
    label.pack()
Esempio n. 2
0
import requests
import robin_stocks as r

config = configparser.ConfigParser()
config.read('config.ini')

totp  = pyotp.TOTP("CHSWL44S5MX7VI2Q").now()
print("Current OTP:", totp)
login = r.login(config.get('authentication', 'email'), config.get('authentication', 'password'), store_session=True, mfa_code=totp)
# print("login data is ", login)

print("===")
print("running test at {}".format(datetime.datetime.now()))
print("===")

profile = r.get_card_transactions()
print(profile)

# info = r.delete_symbols_from_watchlist(['fb','qd'],'Default')
# print(info)

# order = r.orders.order_buy_trailing_stop('BA', 1, 10, trailType='percentage', timeInForce='gtc')
# info = r.get_crypto_historicals('btc')
# print(info)
# info = r.get_stock_historicals(['aapl'])
# info = r.get_option_historicals('spy', '2020-07-01', '307', 'call', 'hour', 'day', 'regular')
# info = r.find_tradable_options_for_stock('spy',strikePrice='307',expirationDate='2020-07-01',optionType='call',info='type')
# info = r.find_options_by_expiration(['aapl'],'2020-07-02')
# info = r.find_options_by_strike(['aapl', 'spy'],'290')
# info = r.find_options_by_expiration_and_strike(['spy', 'aapl'],'2020-07-02', '300')
# info = r.find_options_by_specific_profitability(['fb','aapl'], expirationDate='2020-07-02', optionType='call')
Esempio n. 3
0
    stock_info_line = key + " " + stock_name_val + " " + val[
        "price"] + " " + val["quantity"] + " " + val[
            "average_buy_price"] + " " + val["equity"] + " " + val[
                "equity_change"] + " " + val[
                    "average_buy_price"] + "\n"  # For Microsoft Excel
    #stock_info_line = key + "," + val["name"] + "," + val["price"] + "," + val["quantity"] + val["average_buy_price"] + "," + val["equity"] + "," + val["equity_change"] + "," + val["average_buy_price"] + "\n"

    my_stocks_csv.write(stock_info_line)
    print(stock_info_line)

#print(robin_bot.stocks.find_instrument_data("STPK"))
#print(my_stock_tickers)

profileData = r.load_portfolio_profile()
allTransactions = r.get_bank_transfers()
cardTransactions = r.get_card_transactions()

#Calculate total holdings
deposits = sum(
    float(x['amount']) for x in allTransactions
    if (x['direction'] == 'deposit') and (x['state'] == 'completed'))
withdrawals = sum(
    float(x['amount']) for x in allTransactions
    if (x['direction'] == 'withdraw') and (x['state'] == 'completed'))
debits = sum(
    float(x['amount']['amount']) for x in cardTransactions
    if (x['direction'] == 'debit' and (x['transaction_type'] == 'settled')))
reversal_fees = sum(
    float(x['fees']) for x in allTransactions
    if (x['direction'] == 'deposit') and (x['state'] == 'reversed'))
Esempio n. 4
0
def get_total_gains(password):
    """get_total_gains - Return the total gains for the user's account"""
    with open(ACCOUNT_JSON, 'r') as f:
        account = json.load(f)

    if checkpw(password, account['password']):

        click.echo("Logged in as " + account['email'])
        r.login(account['email'], password)
        profile_data = r.load_portfolio_profile()
        crypto_positions = r.get_crypto_positions()
        all_transactions = r.get_bank_transfers()
        card_transactions = r.get_card_transactions()
        dividends = r.get_total_dividends()

        deposits = sum(
            float(x['amount']) for x in all_transactions
            if (x['direction'] == 'deposit') and (x['state'] == 'completed'))
        withdrawals = sum(
            float(x['amount']) for x in all_transactions
            if (x['direction'] == 'withdraw') and (x['state'] == 'completed'))
        debits = sum(
            float(x['amount']['amount']) for x in card_transactions
            if (x['direction'] == 'debit' and (
                x['transaction_type'] == 'settled')))
        reversal_fees = sum(
            float(x['fees']) for x in all_transactions
            if (x['direction'] == 'deposit') and (x['state'] == 'reversed'))

        money_invested = deposits + reversal_fees - (withdrawals - debits)
        percent_dividend = dividends / money_invested * 100

        profile_equity = float(profile_data['extended_hours_equity'])
        crypto_equity = float(
            crypto_positions[0]['cost_bases'][0]['direct_cost_basis'])
        equity = profile_equity + crypto_equity

        total_gain_minus_dividends = equity - dividends - money_invested
        percent_gain = total_gain_minus_dividends / money_invested * 100

        val = "${:.2f}"
        valp = "%{:.2f}"

        data = {
            '|Total Invested|': [val.format(money_invested)],
            '|Total Equity|': [val.format(equity)],
            '|Net Worth (Dividends)|':
            [(val.format(dividends),
              valp.format(percent_dividend).replace('%-', '-%'))],
            '|Net Worth (Other Gains)|':
            [(val.format(total_gain_minus_dividends),
              valp.format(percent_gain).replace('%-', '-%'))]
        }

        df = pd.DataFrame.from_dict(data)
        click.echo('\n')
        click.echo(df.to_string(index=False))
        click.echo('\n')

    else:
        # Login Unsuccessful
        click.echo("Incorrect Robinhood Password")
Esempio n. 5
0
def PRINT_ALL_PROFILE_AND_ORDERS(save_bool=False,load_bool=False, extra_info_bool=False, csv_bool=False, csv_profile_bool=False, info_type="ALL", sort_alpha_bool=False):

    global run_date_orders # we change this value in here so we mark it as changeable with global keyword

    # info type
    if info_type == "ALL":
        info_type_string = "All Information"
    elif info_type == "PROFILE":
        info_type_string = "Profile Information"
    elif info_type == "FINANCE":
        info_type_string = "Financial Information"

    # print date header
    print(f"Date: {run_date} - Rhood Version: {Version} - {info_type_string}")
    print()

    # preloading
    if load_bool:
        # loading orders from pickle
        ld = load_data(FILENAME) # this is used below this if as well
        run_date_orders = ld['run_date']
        print(f"* Preloading Complete")
        if ld["username"] != loaded_username:
            errext(2, "Loaded finance information of another user, can't do that. Please save current users data first using --save, if you wish to --load it at later point.")
        print()
    else:
        # contacting order via API
        run_date_orders = run_date

    if info_type == "ALL" or info_type == "PROFILE":
        # print account info
        prof_type = ["account","basic","investment","portfolio","security","user"]
        # save profiles to csv if csv_profile_bool
        for prof in prof_type:
            print(f"---{prof} Profile---")
            prof_func = getattr(r.profiles,f"load_{prof}_profile")
            prof_dictionary = prof_func()
            if csv_profile_bool:
                print_to_csv(f"A-{prof}-profile",prof_dictionary)
            print("\n".join([ f"* {i[0]}: {i[1]}" for i in prof_dictionary.items() ]))
            print()

    if info_type == "ALL" or info_type == "FINANCE":
        # print account values
        print(f"--- Gain Information (Experimental) ---")
        print(f"* NOTE: Currently this section does not take into account cash management, options, and crypto. If only stocks are involved, then this section _should_ be accurate.")
        print(f"* NOTE: The profit calculations in this section are inspired by https://github.com/jmfernandes/robin_stocks/blob/master/examples/get_accurate_gains.py")
        print(f"* NOTE: The profit calculations below this section are more accurate as they consider every symbol order + current open positions + dividends")

        profileData = r.load_portfolio_profile()
        allTransactions = r.get_bank_transfers()
        cardTransactions= r.get_card_transactions()

        deposits = sum(float(x['amount']) for x in allTransactions if (x['direction'] == 'deposit') and (x['state'] == 'completed'))
        withdrawals = sum(float(x['amount']) for x in allTransactions if (x['direction'] == 'withdraw') and (x['state'] == 'completed'))
        debits = sum(float(x['amount']['amount']) for x in cardTransactions if (x['direction'] == 'debit' and (x['transaction_type'] == 'settled')))
        reversal_fees = sum(float(x['fees']) for x in allTransactions if (x['direction'] == 'deposit') and (x['state'] == 'reversed'))

        money_invested = deposits + reversal_fees - (withdrawals - debits)
        dividends = r.get_total_dividends()
        percentDividend = dividends/money_invested*100

        equity = float(profileData['equity'])  # author original was extended_hours_equity
        extended_hours_equity_string = profileData['extended_hours_equity']
        if extended_hours_equity_string is not None:
            extended_hours_equity = float(extended_hours_equity_string)
            use_equity = extended_hours_equity
            print("* NOTE: extended_hours_equity exists, using it")
        else:
            extended_hours_equity = None
            use_equity = equity
            print("* NOTE: extended_hours_equity missing, using regular equity instead")
            
        totalGainMinusDividends = use_equity - dividends - money_invested # missing cash_account_debits + i think also missing crypto and options
        percentGain = totalGainMinusDividends/money_invested*100

        print(f"* Reported Deposits: {TOMONEY(deposits)}")
        print(f"* Reported Withdrawals: {TOMONEY(withdrawals)}")
        print(f"* Reported Debits: {TOMONEY(debits)} *** this is wrong right now ***") # <-- why is this 0, it should be all cash_account debits
        print(f"* Reported Reversal Fees: {TOMONEY(reversal_fees)}")
        print(f"* The total money invested is {TOMONEY(money_invested)}")
        print(f"* The total equity is {TOMONEY(equity)}")
        print(f"* NOTE: extended_hours_equity is {TOMONEY(extended_hours_equity)}") # added by me
        print(f"* The net worth has increased {percentDividend:.3f}% due to dividends that amount to {TOMONEY(dividends)}")
        print(f"* The net worth has increased {TOMONEY(percentGain)}% due to other gains that amount to {TOMONEY(totalGainMinusDividends)} *** correct if only stocks & no cash mgmt ***")
        print()

        # print load stock + crypto + options - TIME CONSUMING
        if load_bool:
            # loading orders from pickle
            # no need to reverse, as we already saveed reversed
            print(f"--- Loading Orders (from file) ---")
            ld = load_data(FILENAME) # this is used below this if as well
            run_date_orders = ld['run_date']
            print(f"* loaded order data from '{FILENAME}' which ran on {run_date_orders}")
            print(f"* (S) started stock orders load")
            stock_orders = ld["stock_orders"]
            print(f"* (S) completed stock orders load")
            print(f"* (C) started crypto orders load")
            crypto_orders = ld["crypto_orders"]
            print(f"* (C) completed crypto orders load")
            print(f"* (O) started option orders load")
            option_orders = ld["option_orders"]
            print(f"* (O) completed option orders load")
            print()
        else:
            # contacting order via API
            print(f"--- Loading Orders (from API) ---")
            run_date_orders = run_date
            print(f"* Loading orders via API on {run_date_orders}")
            print(f"* (S) started stock orders load")
            stock_orders = LOAD_STOCK_ORDERS()
            stock_orders.reverse()
            print(f"* (S) completed stock orders load")
            print(f"* (C) started crypto orders load")
            crypto_orders = LOAD_CRYPTO_ORDERS()
            crypto_orders.reverse()
            print(f"* (C) completed crypto orders load")
            print(f"* (O) started option orders load")
            option_orders = LOAD_OPTION_ORDERS()
            option_orders.reverse()
            print(f"* (O) completed option orders load")
            print()

        # print all stock orders (buy and sell)
        stocks_dict = {}
        print(f"--- All Stock Orders ---")
        if stock_orders != []:
            if extra_info_bool: # time consuming shows alot of extra information (like state of orders and more)
                PRINT_STOCK_ORDERS(stock_orders)  ## time consuming
                print()
                if load_bool:
                    print("...loading parsed stock orders...")
                    stocks_dict = ld["stocks_dict"]
                else:
                    print("...parsing stock orders...")
                    stocks_dict = PARSE_STOCK_ORDERS(stock_orders)
                print()
                print(f"--- Parsed Fulfilled Stock Orders ---")
                PRINT_ORDERS_DICTIONARY(stocks_dict)
                print()
            else: # not time consuming
                if load_bool:
                    print("...loading parsed stock orders...")
                    stocks_dict = ld["stocks_dict"]
                else:
                    print("...parsing stock orders...")
                    stocks_dict = PARSE_STOCK_ORDERS(stock_orders)
                PRINT_ORDERS_DICTIONARY(stocks_dict)
                print()

        # print all crypto orders (buy and sell)
        cryptos_dict = {}
        print(f"--- All Crypto Orders ---")
        if crypto_orders != []:
            if extra_info_bool: # time consuming shows alot of extra information (like state of orders and more)
                PRINT_CRYPTO_ORDERS(crypto_orders) ## time consuming
                print()
                if load_bool:
                    print("...loading parsed crypto orders...")
                    cryptos_dict = ld["cryptos_dict"]
                else:
                    print("...parsing crypto orders...")
                    cryptos_dict = PARSE_CRYPTO_ORDERS(crypto_orders)
                print()
                print(f"--- Parsed Fulfilled Crypto Orders ---")
                PRINT_ORDERS_DICTIONARY(cryptos_dict)
                print()
            else: # not time consuming
                if load_bool:
                    print("...loading parsed crypto orders...")
                    cryptos_dict = ld["cryptos_dict"]
                else:
                    print("...parsing crypto orders...")
                    cryptos_dict = PARSE_CRYPTO_ORDERS(crypto_orders)
                PRINT_ORDERS_DICTIONARY(cryptos_dict)
                print()

        # print all option orders (buy and sell)
        options_dict = {}
        print(f"--- All Option Orders ---")
        if option_orders != []: # time consuming shows alot of extra information (like state of orders and more)
            PRINT_OPTION_ORDERS(option_orders)  ## time consuming
            print()
            if load_bool:
                print("...loading parsed option orders...")
                options_dict = ld["options_dict"]
            else:
                print("...parsing option orders...")
                options_dict = PARSE_OPTION_ORDERS(option_orders)
            print()
            print(f"--- Parsed Fulfilled Option Orders ---")
            PRINT_ORDERS_DICTIONARY(options_dict)
            print()
        else:  # not time consuming
            if load_bool:
                print("...loading parsed option orders...")
                options_dict = ld["options_dict"]
            else:
                print("...parsing option orders...")
                options_dict = PARSE_OPTION_ORDERS(option_orders)
            PRINT_ORDERS_DICTIONARY(options_dict)
            print()

        # show open positions
        print("--- Open Positions ---")
        total_stocks_open_amount, total_cryptos_open_amount, total_options_open_amount = (0, 0, 0)
        total_stocks_open_value, total_cryptos_open_value, total_options_open_value = (0, 0, 0)
        sod, cod, ood = [], [], [] # stock open list of dicts, crypto open list of dicts, option open list of dicts
        # stocks
        stocks_open = ld["stocks_open"] if load_bool else LOAD_OPEN_STOCKS()
        sum_of_stocks_open_quantity = sum([ float(i["quantity"]) for i in stocks_open ])
        # if stocks_open != []:
        if sum_of_stocks_open_quantity != 0:
            print()
            print("STOCKS:")
            for i in stocks_open:
                s = URL2SYM(i["instrument"])
                a = float(i["quantity"])
                if a == 0: # skip if empty and not actually an open position
                    continue
                p = find_price_in_open_listdict(s,ld["sod"]) if load_bool else QUOTE_STOCK(s) # p = QUOTE_STOCK(s) # or maybe faster to do this: float(i["average_buy_price"])
                # print("DEBUG-S:",s,p)
                stocks_dict[s].update_current(a,p)
                total_stocks_open_amount += a
                total_stocks_open_value += stocks_dict[s].current_value
                sod.append({ "symbol": s, "quantity": a, "price": p, "value": stocks_dict[s].current_value })
            if sort_alpha_bool:
                sod.sort(key=lambda x: x["symbol"], reverse=False)
            else:
                sod.sort(key=lambda x: float(x["value"]), reverse=False)
            for i in sod:
                s = i["symbol"]
                a = i["quantity"]
                p = i["price"]
                v = i["value"]
                print(f"* OPEN STOCK - {s} x{a} at ${DX(p,5)} each - est current value: ${DX(v,5)}")
            print(f"* TOTAL OPEN STOCKS - {total_stocks_open_amount} stocks for total ${DX(total_stocks_open_value,5)} estimated value")
        # cryptos
        cryptos_open = ld["cryptos_open"] if load_bool else LOAD_OPEN_CRYPTOS()
        sum_of_cryptos_open_quantity = sum([ float(i["quantity"]) for i in cryptos_open ])
        # if cryptos_open != []:
        if sum_of_cryptos_open_quantity != 0:
            print()
            print("CRYPTO:")
            for i in cryptos_open:
                s = i["currency"]["code"] 
                a = float(i["quantity"])
                if a == 0: # skip if empty and not actually an open position
                    continue
                p = QUOTE_CRYPTO(s)
                p = find_price_in_open_listdict(s,ld["cod"]) if load_bool else QUOTE_CRYPTO(s) # p = QUOTE_CRYPTO(s)
                # print("DEBUG-C:",s,p)
                cryptos_dict[s].update_current(a,p)
                total_cryptos_open_amount += a
                total_cryptos_open_value += cryptos_dict[s].current_value
                cod.append({ "symbol": s, "quantity": a, "price": p, "value": cryptos_dict[s].current_value })
            if sort_alpha_bool:
                cod.sort(key=lambda x: x["symbol"], reverse=False)
            else:
                cod.sort(key=lambda x: float(x["value"]), reverse=False)
            for i in cod:
                s = i["symbol"]
                a = i["quantity"]
                p = i["price"]
                v = i["value"]
                print(f"* OPEN CRYPTO - {s} x{a} at ${DX(p,5)} each - est current value: ${DX(v,5)}")
            print(f"* TOTAL OPEN CRYPTO - {total_cryptos_open_amount} stocks for total ${DX(total_cryptos_open_value,5)} estimated value")
        # TODO: options open positions
        options_open = ld["options_open"] if load_bool else LOAD_OPEN_OPTIONS()
        if options_open != []:
            pass
        # show total open amounts
        if stocks_open != [] or cryptos_open != [] or options_open != []:
            total_open_amount = total_stocks_open_amount, total_cryptos_open_amount, total_options_open_amount
            total_open_value = total_stocks_open_value + total_cryptos_open_value + total_options_open_value
            print()
            print("TOTAL:")
            print(f"* total open positions value: ${D2(total_open_value)}")

        # quick inner function for profit printing
        def show_profits_from_orders_dictionary(dictionary, prefix=""):
            total_profit = 0
            total_amount = 0
            # get list of all symbols that are open
            stock_keys = [ i["symbol"] for i in sod ] if sod != [] else []
            crypto_keys = [ i["symbol"] for i in cod ] if cod != [] else []
            option_keys = [ i["symbol"] for i in ood ] if ood != [] else []
            all_keys = stock_keys + crypto_keys + option_keys
            list_dict = []
            # go thru each item in the dictionary which is a multi_order class and run latest_profit and latest_amount (not needed)        
            for sym,orders in dictionary.items():
                last_profit = orders.latest_profit()
                last_amount = orders.latest_amount() # <-- not needed as it fails when stocks split. open stocks make more senses
                ## open_string = " ** currently open **" if sym in all_keys else ""
                open_bool = True if sym in all_keys else False
                list_dict.append({"symbol":sym,"profit":last_profit,"open":open_bool})
                ## print(f"* {sym} net profit ${D2(last_profit)}"+open_string)
                total_profit += last_profit
                total_amount += last_amount
            # sort list by profit (previously we printed list above, and didn't this for loop because we didn't sort)
            if sort_alpha_bool:
                list_dict.sort(key=lambda x: x["symbol"], reverse=False) # increasing
            else:
                list_dict.sort(key=lambda x: float(x["profit"]), reverse=False) # increasing
            for i in list_dict:
                sym = i["symbol"]
                last_profit = i["profit"]
                open_string = " ** currently open **" if i["open"] else ""
                print(f"* {prefix}{sym} net profit ${D2(last_profit)}"+open_string)
            print(f"* {prefix}total net profit ${D2(total_profit)}")
            return (total_profit, total_amount, list_dict)

        # show each stocks profit
        print()
        print(f"--- Profits Based On Orders + Open Positions ---")
        print("* NOTE: For this profit approximation, add up every symbol's sell values, subtract the buy values, and if the symbol is currently open add in the current open value based on current ask price for the symbol")
        print("* NOTE: This is an approximation - albiet a good one, because symbols which are currently open their current ask price is constantly fluctuating.")
        print("* NOTE: If your portfolio has no open symbols, then this is not an approximation but a very close actual value.")
        print("* NOTE: profit per stock = (current open position value) + (sum of all of the sells) - (sum of all of the buy orders)")
        total_stocks_profit, total_stocks_amount, total_cryptos_profit, total_cryptos_amount, total_options_profit, total_options_amount = 0,0,0,0,0,0
        list_dict_of_stock_profits, list_dict_of_crypto_profits, list_dict_of_option_profits = [], [], []
        profits_dict = {}
        if stock_orders != []:
            print()
            print(f"STOCKS:")
            total_stocks_profit, total_stocks_amount, list_dict_of_stock_profits = show_profits_from_orders_dictionary(stocks_dict,"STOCK ")
        if crypto_orders != []:
            print()
            print(f"CRYPTO:")
            total_cryptos_profit, total_cryptos_amount, list_dict_of_crypto_profits = show_profits_from_orders_dictionary(cryptos_dict, "CRYPTO ")
        if option_orders != []:
            print()
            print(f"OPTIONS:")
            total_options_profit, total_options_amount, list_dict_of_option_profits = show_profits_from_orders_dictionary(options_dict, "OPTION ")
        complete_profit = total_stocks_profit + total_cryptos_profit + total_options_profit
        print()
        print("TOTAL NET PROFIT:")
        print(f"* total net profit from stocks, crypto, and options: ${D2(complete_profit)}")
        print()

        # dividend profit
        print(f"--- Profits from Dividends ---")
        rs_divs_list = ld["dividends"] if load_bool else LOAD_DIVIDENDS()
        if rs_divs_list != [] or rs_divs_list is not None: # maybe just checking != [] is enough, doesn't hurt to check for None as well
            divs_list = []
            divs_sum = 0 # can also get divs sum with API: r.get_total_dividends()
            for i in rs_divs_list:
                symbol = URL2SYM(i["instrument"])
                amount_paid = float(i["amount"])
                date_string = i["paid_at"]
                state = i["state"]
                d = orders.dividend(symbol,amount_paid,date_string,state,run_date)
                divs_list.append(d)
                if state == "paid":
                    divs_sum += amount_paid

            # sort by value or alpha ---- but we will always sort by date
            # if sort_alpha_bool:
            #     sort(divs_list,key=lambda x: x.symbol_name)
            # else:
            #    sort(divs_list,key=lambda x: x.amount_paid)
            divs_list.sort(key=lambda x: x.date_epoch)
            for i in divs_list:
                print(f"* dividend from {i.symbol_name} on {i.date_nice()} for ${D2(i.payed_amount)} ({i.state})")
            print(f"TOTAL PAID DIVIDEND PROFIT: ${D2(divs_sum)}")
            print()

        print("--- Total Profit (Net Profit + Dividends) ---")
        complete_profit_plus_divs = complete_profit + divs_sum
        print(f"* total profit from stocks, crypto, and options + dividends: ${D2(complete_profit_plus_divs)}")
        print()

    ### TESTING
    # print(f"--- TESTING SOME VALUES ---")
    # sum_sells = 0
    # sum_buys = 0
    # sum_profits = 0
    # for sf in stocks_dict.values():
    #     a,b,c,d,e,f = sf.print_some_values() # prints and sets
    #     sum_sells += b
    #     sum_buys += c
    #     sum_profits += d
    # rat_pps = (sum_profits / sum_sells)*100
    # rat_ppb = (sum_profits / sum_buys)*100
    # print(f"** {sum_sells=} {sum_buys=} {sum_profits=} {rat_pps=} {rat_ppb=} **")
    # print()

    # print extra info footer
    print(f"--- Final Notes ---")

    # if profile info was saved to csv
    dir_full = get_save_dir()

    if info_type == "ALL" or info_type == "PROFILE":
        if csv_profile_bool:
            print(f"* saved profile data csvs to '{dir_full}' directory")

    if info_type == "PROFILE" and csv_profile_bool == False:
        print("* none")

    # if we loaded order data from api or dat.pkl file
    if info_type == "ALL" or info_type == "FINANCE":
        if load_bool:
            print(f"* loaded order data from '{FILENAME}' which ran on {run_date_orders}")
        else:
            print(f"* loaded order data from robinhood API run date {run_date_orders}")
    
    # save to order , open , and profit to csv
    if info_type == "ALL" or info_type == "FINANCE":
        if csv_bool:
            if stock_orders != []:
                print(f"* saving stock orders + open positions + net profits csvs to '{dir_full}' directory")
                print_all_stocks_to_csv(stock_orders)
                print_to_csv("All-Profits-Stocks",list_dict_of_stock_profits)
                if sod != []:
                    print_to_csv("All-Open-Stocks",sod)
                print(f"* saved stock csvs")
            if crypto_orders != []:
                print(f"* saving crypto orders + open positions + net profits csvs to '{dir_full}' directory")
                print_all_crypto_to_csv(crypto_orders)
                print_to_csv("All-Profits-Crypto",list_dict_of_crypto_profits)
                if cod != []:
                    print_to_csv("All-Open-Crypto",cod)
                print(f"* saved crypto csvs")
            if option_orders != []:
                print(f"* saving option orders + open positions + net profits csvs to '{dir_full}' directory")
                print_all_options_to_csv(option_orders)
                print_to_csv("All-Profits-Options",list_dict_of_option_profits)
                if ood != []:
                    print_to_csv("All-Open-Options",ood)
                print(f"* saved option csvs")
            if rs_divs_list != []:
                print(f"* saving dividends csv to '{dir_full}'")
                print_to_csv("All-Dividends",rs_divs_list)
    
        # Save api data to pickle file dat.pkl so we can use --load in future to load faster (but of course then its not live data)
        if save_bool:
            save_data(FILENAME, so = stock_orders, co = crypto_orders, oo = option_orders, sd = stocks_dict, cd = cryptos_dict, od = options_dict, soo = stocks_open, coo = cryptos_open, ooo = options_open, sod = sod, cod = cod, ood = ood, divs = rs_divs_list, verify_bool = True)