-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathallyAPI.py
154 lines (149 loc) · 6.15 KB
/
allyAPI.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Nelson Dane
# Ally API
import os
import sys
import ally
from dotenv import load_dotenv
# Initialize Ally
def ally_init():
# Initialize .env file
load_dotenv()
# Import Ally account
if not os.getenv("ALLY_CONSUMER_KEY") or not os.getenv("ALLY_CONSUMER_SECRET") or not os.getenv("ALLY_OAUTH_TOKEN") or not os.getenv("ALLY_OAUTH_SECRET") or not os.getenv("ALLY_ACCOUNT_NBR"):
print("Ally not found, skipping...")
return None
ALLY_CONSUMER_KEY = os.environ["ALLY_CONSUMER_KEY"]
ALLY_CONSUMER_SECRET = os.environ["ALLY_CONSUMER_SECRET"]
ALLY_OAUTH_TOKEN = os.environ["ALLY_OAUTH_TOKEN"]
ALLY_OAUTH_SECRET = os.environ["ALLY_OAUTH_SECRET"]
ALLY_ACCOUNT_NBR = os.environ["ALLY_ACCOUNT_NBR"]
# Initialize Ally account
try:
a = ally.Ally()
print("Logging in to Ally...")
an = a.balances()
account_numbers = an['account'].values
print(f"Ally account numbers: {account_numbers}")
except Exception as e:
print(f'Ally: Error logging in: {e}')
return None
print("Logged in to Ally!")
return a
# Function to get the current account holdings
async def ally_holdings(a, ctx=None):
print("==============================")
print("Ally Holdings")
print("==============================")
print()
# Make sure init didn't return None
if a is None:
print("Error: No Ally account")
return None
try:
# Get account holdings
ab = a.balances()
a_value = ab['accountvalue'].values
for value in a_value:
print(f"Ally account value: ${value}")
if ctx:
await ctx.send(f"Ally account value: ${value}")
# Print account stock holdings
ah = a.holdings()
account_symbols = (ah['sym'].values).tolist()
qty = (ah['qty'].values).tolist()
current_price = (ah['marketvalue'].values).tolist()
print("Ally account symbols:")
if ctx:
await ctx.send("Ally account symbols:")
for symbol in account_symbols:
# Set index for easy use
i = account_symbols.index(symbol)
print(f"{symbol}: {float(qty[i])} @ ${round(float(current_price[i]), 2)} = ${round(float(qty[i]) * float(current_price[i]), 2)}")
if ctx:
await ctx.send(f"{symbol}: {float(qty[i])} @ ${round(float(current_price[i]), 2)} = ${round(float(qty[i]) * float(current_price[i]), 2)}")
except Exception as e:
print(f'Ally: Error getting account holdings: {e}')
if ctx:
await ctx.send(f'Ally: Error getting account holdings: {e}')
# Function to buy/sell stock on Ally
async def ally_transaction(a, action, stock, amount, price, time, DRY=True, ctx=None):
print()
print("==============================")
print("Ally")
print("==============================")
print()
action = action.lower()
stock = stock.upper()
amount = int(amount)
# Make sure init didn't return None
if a is None:
print("Error: No Ally account")
return None
# Set the action
if type(price) is str and price.lower() == "market":
price = ally.Order.Market()
elif type(price) is float or type(price) is int:
price = ally.Order.Limit(limpx=float(price))
try:
# Create order
o = ally.Order.Order(
buysell = action,
symbol = stock,
price = price,
time = time,
qty = amount
)
# Print order preview
print(str(o))
# Submit order
o.orderid
if not DRY:
a.submit(o, preview=False)
else:
print(f"Ally: Running in DRY mode. Trasaction would've been: {action} {amount} of {stock}")
if ctx:
await ctx.send(f"Ally: Running in DRY mode. Trasaction would've been: {action} {amount} of {stock}")
if o.orderid:
print(f"Ally: Order {o.orderid} submitted")
if ctx:
await ctx.send(f"Ally: Order {o.orderid} submitted")
else:
print(f"Ally: Order not submitted")
if ctx:
await ctx.send(f"Ally: Order not submitted")
except Exception as e:
ally_call_error = "Error: For your security, certain symbols may only be traded by speaking to an Ally Invest registered representative. Please call 1-855-880-2559 if you need further assistance with this order."
if "500 server error: internal server error for url:" in str(e).lower():
# If selling too soon, then an error is thrown
if action == "sell":
print(ally_call_error)
if ctx:
await ctx.send(ally_call_error)
# If the message comes up while buying, then try again with a limmit order
elif action == "buy":
print(f"Ally: Error placing market buy, trying again with limit order...")
if ctx:
await ctx.send(f"Ally: Error placing market buy, trying again with limit order...")
# Need to get stock price (compare bid, ask, and last)
try:
# Get stock values
quotes = a.quote(
stock,
fields=['bid','ask','last'],
)
# Add 1 cent to the highest value of the 3 above
new_price = (max([float(quotes['last']), float(quotes['bid']), float(quotes['ask'])])) + 0.01
# Run function again with limit order
await ally_transaction(a, action, stock, amount, new_price, time, DRY, ctx)
except Exception as e:
print(f"Ally: Failed to place limit order: {e}")
if ctx:
await ctx.send(f"Ally: Failed to place limit order: {e}")
elif type(price) is not str:
print(f"Ally: Error placing limit order: {e}")
if ctx:
await ctx.send(f"Ally: Error placing limit order: {e}")
else:
print(f'Ally: Error submitting order: {e}')
if ctx:
await ctx.send(f'Ally: Error submitting order: {e}')