diff --git a/autoRSA.py b/autoRSA.py index f211a35c..d18f895b 100644 --- a/autoRSA.py +++ b/autoRSA.py @@ -31,6 +31,7 @@ printAndDiscord, stockOrder, updater, + printFinalTransactions, ) from publicAPI import * from robinhoodAPI import * @@ -182,6 +183,8 @@ def fun_run(orderObj: stockOrder, command, botObj=None, loop=None): print(f"Error in {fun_name} with {broker}: {ex}") print(orderObj) print() + if second_command == "_transaction": + printFinalTransactions(loop) printAndDiscord("All commands complete in all brokers", loop) else: print(f"Error: {command} is not a valid command") diff --git a/chaseAPI.py b/chaseAPI.py index 7c7a2c66..71c9db14 100644 --- a/chaseAPI.py +++ b/chaseAPI.py @@ -16,6 +16,7 @@ printAndDiscord, printHoldings, stockOrder, + printConfirm, ) @@ -318,31 +319,16 @@ def chase_transaction( ) else: pprint.pprint(messages["ORDER CONFIRMATION"]) - printAndDiscord( - ( - f"{key} account {account}: The order verification was " - + ( - "successful" - if messages["ORDER CONFIRMATION"] - not in [ + if messages["ORDER CONFIRMATION"] not in [ "", "No order confirmation page found. Order Failed.", - ] - else "unsuccessful" - ) - ), - loop, - ) - if ( - messages["ORDER INVALID"] - != "No invalid order message found." - ): - printAndDiscord( - f"{key} account {account}: The order verification produced the following messages: {messages['ORDER INVALID']}", - loop, - ) + ]: + printConfirm(key, account, orderObj.get_action(), orderObj.get_amount(), ticker, loop, False) + else: + printConfirm(key, account, orderObj.get_action(), orderObj.get_amount(), ticker, loop, True, messages['ORDER INVALID']) + except Exception as e: - printAndDiscord(f"{key} {account}: Error submitting order: {e}", loop) + printConfirm(key, account, orderObj.get_action(), orderObj.get_amount(), ticker, loop, True, e) print(traceback.format_exc()) continue ch_session.close_browser() diff --git a/fennelAPI.py b/fennelAPI.py index 7b880b9b..5ab37142 100644 --- a/fennelAPI.py +++ b/fennelAPI.py @@ -11,6 +11,7 @@ printAndDiscord, printHoldings, stockOrder, + printConfirm, ) @@ -140,11 +141,8 @@ def fennel_transaction(fbo: Brokerage, orderObj: stockOrder, loop=None): message = "Success" if order.get("data", {}).get("createOrder") != "pending": message = order.get("data", {}).get("createOrder") - printAndDiscord( - f"{key}: {orderObj.get_action()} {orderObj.get_amount()} of {s} in {account}: {message}", - loop, - ) + printConfirm(key, account, orderObj.get_action(), orderObj.get_amount(), s, loop, False, message) except Exception as e: - printAndDiscord(f"{key} {account}: Error placing order: {e}", loop) + printConfirm(key, account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, e) print(traceback.format_exc()) continue diff --git a/fidelityAPI.py b/fidelityAPI.py index 89d5b6bf..0d836884 100644 --- a/fidelityAPI.py +++ b/fidelityAPI.py @@ -27,6 +27,7 @@ printHoldings, stockOrder, type_slowly, + printConfirm, ) @@ -588,10 +589,7 @@ def fidelity_transaction(fidelity_o: Brokerage, orderObj: stockOrder, loop=None) WebDriverWait(driver, 10).until(check_if_page_loaded) sleep(1) # Send confirmation - printAndDiscord( - f"{key} {account_label}: {orderObj.get_action()} {orderObj.get_amount()} shares of {s}", - loop, - ) + printConfirm(key, account_label, orderObj.get_action(), orderObj.get_amount(), s, loop, False) except NoSuchElementException: # Check for error WebDriverWait(driver, 10).until( @@ -609,10 +607,7 @@ def fidelity_transaction(fidelity_o: Brokerage, orderObj: stockOrder, loop=None) driver.execute_script( "arguments[0].click();", error_dismiss ) - printAndDiscord( - f"{key} account {account_label}: {orderObj.get_action()} {orderObj.get_amount()} shares of {s}. DID NOT COMPLETE! \nEither this account does not have enough shares, or an order is already pending.", - loop, - ) + printConfirm(key, account_label, orderObj.get_action(), orderObj.get_amount(), s, loop, True, "\nEither this account does not have enough shares, or an order is already pending.") # Send confirmation else: printAndDiscord( @@ -621,6 +616,7 @@ def fidelity_transaction(fidelity_o: Brokerage, orderObj: stockOrder, loop=None) ) sleep(3) except Exception as err: + printConfirm(key, account_label, orderObj.get_action(), orderObj.get_amount(), s, loop, True, err) fidelity_error(driver, err) continue print() diff --git a/firstradeAPI.py b/firstradeAPI.py index eb6aa5f5..47512b15 100644 --- a/firstradeAPI.py +++ b/firstradeAPI.py @@ -18,6 +18,7 @@ printAndDiscord, printHoldings, stockOrder, + printConfirm, ) @@ -159,24 +160,15 @@ def firstrade_transaction(firstrade_o: Brokerage, orderObj: stockOrder, loop=Non print("The order verification produced the following messages: ") pprint.pprint(order_conf) - printAndDiscord( - ( - f"{key} account {print_account}: The order verification was " - + "successful" - if order_conf["error"] == "" - else "unsuccessful" - ), - loop, - ) - if not order_conf["error"] == "": - printAndDiscord( - f"{key} account {print_account}: The order verification produced the following messages: {order_conf}", - loop, - ) + if order_conf["error"] == "": + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False) + else: + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, order_conf) except Exception as e: printAndDiscord( f"{key} {print_account}: Error submitting order: {e}", loop ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, f"Error submitting order: {e}") print(traceback.format_exc()) continue sleep(1) diff --git a/helperAPI.py b/helperAPI.py index 8943d7ff..6b165811 100644 --- a/helperAPI.py +++ b/helperAPI.py @@ -29,6 +29,8 @@ # Create task queue task_queue = Queue() +transactions = {} + class stockOrder: def __init__(self): @@ -760,3 +762,44 @@ def printHoldings(brokerObj: Brokerage, loop=None, mask=True): EMBED["fields"].append(field) printAndDiscord(EMBED, loop, True) print("==============================") + + +def printConfirm(key, account, action, amount, ticker, loop, error, prints=None): + if key not in transactions: + transactions[key] = [0, 1] if error else [1, 1] + else: + if not error: + transactions[key][0] += 1 + transactions[key][1] += 1 + + message = f"{':green_square:' if not error else ':red_square:'} {key} {account}: {action} {amount} shares of {ticker}" + if error: + message += "DID NOT COMPLETE!" + if prints is not None: + message += f": {prints}" + printAndDiscord(message, loop) + + +def printFinalTransactions(loop): + EMBED = { + "title": "Transactions", + "color": 3447003, + "fields": [], + } + for key, value in transactions.items(): + field = { + "name": key, + "inline": False, + } + if value[0] == 0: + message = ":red_square:" + elif value[0] < value[1]: + message = ":orange_square:" + elif value[0] == value[1]: + message = ":green_square:" + else: + message = "?????" + + field["value"] = f"{message} {value[0]}/{value[1]}" + EMBED["fields"].append(field) + printAndDiscord(EMBED, loop, True) diff --git a/publicAPI.py b/publicAPI.py index 3f069ffd..506a2db0 100644 --- a/publicAPI.py +++ b/publicAPI.py @@ -12,6 +12,7 @@ printAndDiscord, printHoldings, stockOrder, + printConfirm, ) @@ -133,12 +134,8 @@ def public_transaction(pbo: Brokerage, orderObj: stockOrder, loop=None): is_dry_run=orderObj.get_dry(), ) if order["success"] is True: - order = "Success" - printAndDiscord( - f"{key}: {orderObj.get_action()} {orderObj.get_amount()} of {s} in {print_account}: {order}", - loop, - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False) except Exception as e: - printAndDiscord(f"{print_account}: Error placing order: {e}", loop) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, e) traceback.print_exc() continue diff --git a/robinhoodAPI.py b/robinhoodAPI.py index 8686ffeb..7a84b952 100644 --- a/robinhoodAPI.py +++ b/robinhoodAPI.py @@ -8,7 +8,7 @@ import robin_stocks.robinhood as rh from dotenv import load_dotenv -from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder +from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder, printConfirm def login_with_cache(pickle_path, pickle_name): @@ -179,21 +179,15 @@ def robinhood_transaction(rho: Brokerage, orderObj: stockOrder, loop=None): message = "Success" if limit_order.get("non_field_errors") is not None: message = limit_order["non_field_errors"] - printAndDiscord( - f"{key}: {orderObj.get_action()} {orderObj.get_amount()} of {s} in {print_account} @ {price}: {message}", - loop, - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False, f"@ {price}: {message}") else: message = "Success" if market_order.get("non_field_errors") is not None: message = market_order["non_field_errors"] - printAndDiscord( - f"{key}: {orderObj.get_action()} {orderObj.get_amount()} of {s} in {print_account}: {message}", - loop, - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False, message) except Exception as e: traceback.format_exc() - printAndDiscord(f"{key} Error submitting order: {e}", loop) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, e) else: printAndDiscord( f"{key} {print_account} Running in DRY mode. Transaction would've been: {orderObj.get_action()} {orderObj.get_amount()} of {s}", diff --git a/schwabAPI.py b/schwabAPI.py index aee849b7..21a11b3a 100644 --- a/schwabAPI.py +++ b/schwabAPI.py @@ -8,7 +8,7 @@ from dotenv import load_dotenv from schwab_api import Schwab -from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder +from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder, printConfirm def schwab_init(SCHWAB_EXTERNAL=None): @@ -110,15 +110,10 @@ def schwab_transaction(schwab_o: Brokerage, orderObj: stockOrder, loop=None): account_id=account, dry_run=orderObj.get_dry(), ) - printAndDiscord( - ( - f"{key} account {print_account}: The order verification was " - + "successful" - if success - else "unsuccessful, retrying..." - ), - loop, - ) + if success: + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False, messages) + else: + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, "unsuccessful, retrying...") if not success: messages, success = obj.trade( ticker=s, @@ -127,22 +122,11 @@ def schwab_transaction(schwab_o: Brokerage, orderObj: stockOrder, loop=None): account_id=account, dry_run=orderObj.get_dry(), ) - printAndDiscord( - ( - f"{key} account {print_account}: The order verification was " - + "retry successful" - if success - else "retry unsuccessful" - ), - loop, - ) - printAndDiscord( - f"{key} account {print_account}: The order verification produced the following messages: {messages}", - loop, - ) + if success: + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False, messages) + else: + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, messages) except Exception as e: - printAndDiscord( - f"{key} {print_account}: Error submitting order: {e}", loop - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, e) print(traceback.format_exc()) sleep(1) diff --git a/tradierAPI.py b/tradierAPI.py index ccb4df7d..a504c5cf 100644 --- a/tradierAPI.py +++ b/tradierAPI.py @@ -9,7 +9,7 @@ import requests from dotenv import load_dotenv -from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder +from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder, printConfirm def make_request( @@ -203,15 +203,9 @@ def tradier_transaction(tradier_o: Brokerage, orderObj: stockOrder, loop=None): ) continue if json_response.get("order", {}).get("status") is not None: - printAndDiscord( - f"Tradier account {print_account}: {orderObj.get_action()} {orderObj.get_amount()} of {s}: {json_response['order']['status']}", - loop=loop, - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False, json_response['order']['status']) continue - printAndDiscord( - f"Tradier account {print_account} Error: This order did not route. JSON response: {json.dumps(json_response, indent=2)}", - loop=loop, - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, f"Error: This order did not route. JSON response: {json.dumps(json_response, indent=2)}") except Exception as e: printAndDiscord( f"Tradier account {print_account} Error: {e}", loop=loop diff --git a/vanguardAPI.py b/vanguardAPI.py index e9c23684..f8b029b8 100644 --- a/vanguardAPI.py +++ b/vanguardAPI.py @@ -17,6 +17,7 @@ printAndDiscord, printHoldings, stockOrder, + printConfirm, ) @@ -218,33 +219,16 @@ def vanguard_transaction(vanguard_o: Brokerage, orderObj: stockOrder, loop=None) else: if messages["ORDER CONFIRMATION"] != "": pprint.pprint(messages["ORDER CONFIRMATION"]) - printAndDiscord( - ( - f"{key} account {print_account}: The order verification was " - + ( - "successful" - if messages["ORDER CONFIRMATION"] - not in [ + if messages["ORDER CONFIRMATION"] not in [ "", "No order confirmation page found. Order Failed.", - ] - else "unsuccessful" - ) - ), - loop, - ) - if ( - messages["ORDER INVALID"] - != "No invalid order message found." - ): - printAndDiscord( - f"{key} account {print_account}: The order verification produced the following messages: {messages['ORDER INVALID']}", - loop, - ) + ]: + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False) + else: + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, messages['ORDER INVALID']) + except Exception as e: - printAndDiscord( - f"{key} {print_account}: Error submitting order: {e}", loop - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, f"Error submitting order: {e}") print(traceback.format_exc()) continue obj.close_browser() diff --git a/webullAPI.py b/webullAPI.py index 01497b20..0a4842c2 100644 --- a/webullAPI.py +++ b/webullAPI.py @@ -8,7 +8,7 @@ from dotenv import load_dotenv from webull import webull -from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder +from helperAPI import Brokerage, maskString, printAndDiscord, printHoldings, stockOrder, printConfirm MAX_WB_RETRIES = 3 # Number of times to retry logging in if not successful MAX_WB_ACCOUNTS = 11 # Different account types @@ -197,14 +197,9 @@ def webull_transaction(wbo: Brokerage, orderObj: stockOrder, loop=None): # Place normal order order = place_order(obj, internal_account, orderObj, s) if order: - printAndDiscord( - f"{key}: {orderObj.get_action()} {orderObj.get_amount()} of {s} in {print_account}: Success", - loop, - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, False) except Exception as e: - printAndDiscord( - f"{key} {print_account}: Error placing order: {e}", loop - ) + printConfirm(key, print_account, orderObj.get_action(), orderObj.get_amount(), s, loop, True, e) print(traceback.format_exc()) continue finally: