Example #1
0
 def get_cash(self):
     logging.info('Getting actual cash value...')
     profile = robin_stocks.load_account_profile()
     self.portfolio_cash = round(float(profile['portfolio_cash']), 2)
     self.buying_power = round(float(profile['buying_power']), 2)
     self.cash = round(float(profile['cash']), 2)
     self.unsettled_funds = round(float(profile['unsettled_funds']), 2)
     self.unsettled_debit = round(float(profile['unsettled_debit']), 2)
     self.cash_held_for_collateral = round(
         float(profile['cash_held_for_options_collateral']), 2)
     logging.info('Getting cash deposited/withdrawn...')
     transfers = robin_stocks.get_bank_transfers()
     for transfer in transfers:
         if transfer[
                 'cancel'] is not None or transfer['state'] != 'completed':
             continue
         amount = round(float(transfer['amount']), 2)
         fees = round(float(transfer['fees']), 2)
         event_time = utc_to_eastern(transfer['created_at'])
         if transfer['direction'] == 'deposit':
             logging.info(
                 f'Adding deposit of ${amount} with a fee of {fees} at {event_time.isoformat()}'
             )
             self.total_deposited += round(amount - fees, 2)
         else:
             logging.info(
                 f'Adding withdrawl of ${amount} with a fee of {fees} at {event_time.isoformat()}'
             )
             self.total_withdrawn += round(amount + fees, 2)
Example #2
0
def get_total_gains_minus_dividends():
    """ Returns the amount of money you've gained/lost through trading since the creation of your account, minus dividends
    """
    profileData = r.load_portfolio_profile()
    print(profileData)
    allTransactions = r.get_bank_transfers()
    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'))
    money_invested = deposits - withdrawals
    print(deposits)
    dividends = r.get_total_dividends()
    percentDividend = dividends/money_invested*100
    totalGainMinusDividends =float(profileData['extended_hours_equity'])-dividends-money_invested
    return totalGainMinusDividends
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()
Example #4
0
Note: load_portfolio_profile() contains some other useful breakdowns of equity.
Print profileData and see what other values you can play around with.

'''

#!!! Fill out username and password
username = ''
password = ''
#!!!

login = r.login(username, password)

profileData = r.load_portfolio_profile()
#print(profileData)
allTransactions = r.get_bank_transfers()

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'))
money_invested = deposits - withdrawals

dividends = r.get_total_dividends()
percentDividend = dividends / money_invested * 100

totalGainMinusDividends = float(
    profileData['extended_hours_equity']) - dividends - money_invested
extendedHours = float(profileData['extended_hours_equity'])
Example #5
0
'''
Robinhood includes dividends as part of your net gain. This script removes
dividends from net gain to figure out how much your stocks/options have paid
off.
Note: load_portfolio_profile() contains some other useful breakdowns of equity.
Print profileData and see what other values you can play around with.
'''

#!!! Fill out username and password

#!!!

login = robin_stocks.login(username,password)

profileData = robin_stocks.load_portfolio_profile()
#print(profileData)
allTransactions = robin_stocks.get_bank_transfers()

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'))
money_invested = deposits - withdrawals

dividends = robin_stocks.get_total_dividends()
percentDividend = dividends/money_invested*100

totalGainMinusDividends =float(profileData['extended_hours_equity'])-dividends-money_invested
percentGain = totalGainMinusDividends/money_invested*100

print("The total money invested is {}".format(money_invested))
print("The net worth has increased {:0.2}% due to dividends".format(percentDividend))
print("The net worth has increased {:0.3}% due to other gains".format(percentGain))
Example #6
0
def import_portfolio_robinhood(access_token,
                               username=None,
                               password=None,
                               name="Robinhood",
                               free_stock=False):
    """
    Accesses Robinhood account and downloads transactions 

    Parameters
    ==========
    username : Robinhood username
    password : Robinhood account password
    name : desired portfolio name 
    free_stock : include a free stock not captured by transaction history (see below)

    Returns
    =======
    df : dataframe with transactions
    p : portfolio (Portfolio class object)

    """
    if not access_token:
        if username is None:
            username = getpass("Username: "******"Password: "******"Parsing orders ...")

    # pre-pull all tickers before creating order history df
    Tickerset = []
    for order in orders:
        if len(order["executions"]):
            Tickerset.append(order["instrument"])
    Tickerset = list(set(Tickerset))

    # make a lookup dict for ticker symbols
    Tickersymbols = {}
    for element in Tickerset:
        Tickersymbols[element] = r.get_instrument_by_url(element)["symbol"]

    for order in orders:
        if len(order["executions"]):
            Date.append(pd.to_datetime(order["last_transaction_at"]))
            Transaction.append(order["side"])
            Ticker.append(Tickersymbols[order["instrument"]])
            Currency.append("USD")
            Price.append(order["average_price"])
            Quantity.append(order["quantity"])

    # add deposits
    transfers = r.get_bank_transfers()
    print("Parsing bank transfers ...")
    for transfer in transfers:
        if transfer["cancel"] is None:
            Date.append(pd.to_datetime(transfer["created_at"]))
            Transaction.append(transfer["direction"])
            Ticker.append(None)
            Currency.append("USD")
            Price.append(1.0)
            Quantity.append(transfer["amount"])

    # add dividends
    dividends = r.get_dividends()
    print("Parsing dividends ...")
    for dividend in dividends:
        if dividend["state"] == "paid":
            Date.append(pd.to_datetime(dividend["paid_at"]))
            Transaction.append("dividend")
            Ticker.append(Tickersymbols[dividend["instrument"]])
            Currency.append("USD")
            Price.append(1.0)
            Quantity.append(dividend["amount"])

    if free_stock == True:
        # include free stock (Robinhood promotion, not included in transaction history)
        print("Adding promotional stock ...")
        Date.append(pd.to_datetime("2/1/18"))
        Transaction.append("buy")
        Ticker.append("CHK")
        Currency.append("USD")
        Price.append(0.0)
        Quantity.append(1.0)

    # build dataframe
    d = {
        "Date": Date,
        "Transaction": Transaction,
        "Ticker": Ticker,
        "Currency": Currency,
        "Price": pd.to_numeric(Price),
        "Quantity": pd.to_numeric(Quantity),
    }
    df = pd.DataFrame(data=d)

    # strip time of day information
    df.Date = df.Date.map(lambda x: x.strftime("%m-%d-%Y"))
    df.Date = pd.to_datetime(df.Date)

    # create a new portfolio object
    p = Portfolio(name=name)

    # parse
    p = parse_portfolio(df, p)

    return p
Example #7
0
def import_portfolio_robinhood(username=None,
                               password=None,
                               name="Robinhood",
                               free_stock=False):
    """
    Accesses Robinhood account and downloads transactions 

    Parameters
    ==========
    username : Robinhood username
    password : Robinhood account password
    name : desired portfolio name 
    free_stock : include a free stock not captured by transaction history (see below)

    Returns
    =======
    df : dataframe with transactions
    p : portfolio (Portfolio class object)

    """
    import robin_stocks as r
    from getpass import getpass

    if username is None: username = getpass("Username: "******"Password: "******"Parsing orders ...")
    for order in orders:
        if len(order['executions']):
            Date.append(pd.to_datetime(order['last_transaction_at']))
            Transaction.append(order['side'])
            Ticker.append(
                r.get_instrument_by_url(order['instrument'])['symbol'])
            Currency.append('USD')
            Price.append(order['average_price'])
            Quantity.append(order['quantity'])

    # add deposits
    transfers = r.get_bank_transfers()
    print("Parsing bank transfers ...")
    for transfer in transfers:
        if transfer['cancel'] is None:
            Date.append(pd.to_datetime(transfer['created_at']))
            Transaction.append('deposit')
            Ticker.append(None)
            Currency.append('USD')
            Price.append(1.0)
            Quantity.append(transfer['amount'])

    # add dividends
    dividends = r.get_dividends()
    print("Parsing dividends ...")
    for dividend in dividends:
        if dividend['state'] == 'paid':
            Date.append(pd.to_datetime(dividend['paid_at']))
            Transaction.append('dividend')
            Ticker.append(
                r.get_instrument_by_url(dividend['instrument'])['symbol'])
            Currency.append('USD')
            Price.append(
                float(dividend['amount']) / float(dividend['position']))
            Quantity.append(dividend['position'])

    if free_stock == True:
        # include free stock (Robinhood promotion, not included in transaction history)
        print("Adding promotional stock ...")
        Date.append(pd.to_datetime('2/1/18'))
        Transaction.append('buy')
        Ticker.append('CHK')
        Currency.append('USD')
        Price.append(0.0)
        Quantity.append(1.0)

    # build dataframe
    d = {
        'Date': Date,
        'Transaction': Transaction,
        'Ticker': Ticker,
        'Currency': Currency,
        'Price': pd.to_numeric(Price),
        'Quantity': pd.to_numeric(Quantity)
    }
    df = pd.DataFrame(data=d)

    # strip time of day information
    df.Date = df.Date.map(lambda x: x.strftime('%m-%d-%Y'))
    df.Date = pd.to_datetime(df.Date)

    # create a new portfolio object
    p = Portfolio(name=name)

    # parse
    p = parse_portfolio(df, p)

    return p
Example #8
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")
Example #9
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)