-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathUpdateSecurities_MD.py
167 lines (148 loc) · 7.13 KB
/
UpdateSecurities_MD.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
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env python
# Python script to be run in Moneydance to perform amazing feats of financial scripting
# Set to your API key with alphavantage.co
apikey = 'YOUR_API_KEY_GOES_HERE'
# initialize lists used for security data
mapCurrent = []
mapDates = []
mapAccounts = []
try:
import ssl
except ImportError:
message = "error: no ssl support"
print message;
from com.infinitekind.moneydance.model import *
from urllib2 import Request, urlopen, URLError, HTTPError
import json
import sys
import time
# Shamelessly copied from moneydance developer page and modified for my own evil purposes
def setPriceForSecurity(currencies, symbol, price, high, low, volume, dateint):
#print 'setting price for ' + symbol + ': $' + str(price)
price = 1/price
security = currencies.getCurrencyByTickerSymbol(symbol)
if not security:
return
if dateint:
snapsec = security.setSnapshotInt(dateint, price)
snapsec.setUserDailyHigh(1/high)
snapsec.setUserDailyLow(1/low)
snapsec.setDailyVolume(volume)
snapsec.syncItem()
security.setUserRate(price)
security.syncItem()
def setPriceForCurrency(currencies, symbol, price, dateint):
#print 'setting price for ' + symbol + ': $' + str(price)
price = 1/price
currency = currencies.getCurrencyByIDString(symbol)
if not currency:
return
if dateint:
snapsec = currency.setSnapshotInt(dateint, price)
snapsec.syncItem()
currency.setUserRate(price)
currency.syncItem()
def loadAccounts(parentAcct):
# This function is a derivative of Mike Bray's Moneydance 2015 Security Price Load module (LoadPricesWindow.java) code and has been modified to work in python
# Original code located here: https://bitbucket.org/mikerb/moneydance-2015/src/346c42555a9ec4be2b05ef5c4469e183135db4cc/src/com/moneydance/modules/features/securitypriceload/?at=master
# Get list of accounts to iterate through
sz = parentAcct.getSubAccountCount();
i = 0
for i in xrange(0,sz):
acct = parentAcct.getSubAccount(i)
if acct.getAccountType() == parentAcct.AccountType.valueOf("SECURITY") :
if(acct.getCurrentBalance() != 0 ):
ctTicker = acct.getCurrencyType();
if (ctTicker != None):
if (ctTicker.getTickerSymbol() != ''):
listSnap = ctTicker.getSnapshots();
iSnapIndex = listSnap.size()-1;
if (iSnapIndex < 0):
mapCurrent.append((ctTicker.getTickerSymbol(), 1.0, ctTicker.getName()));
mapDates.append((ctTicker.getTickerSymbol(),0));
mapAccounts.append((ctTicker.getTickerSymbol(),acct));
else:
ctssLast = listSnap.get(iSnapIndex);
if (ctssLast != None):
mapCurrent.append((ctTicker.getTickerSymbol(),1.0/ctssLast.getUserRate(),ctTicker.getName()));
mapDates.append((ctTicker.getTickerSymbol(), ctssLast.getDateInt()));
mapAccounts.append((ctTicker.getTickerSymbol(), acct));
loadAccounts(acct);
def buildUrl(func, symbol, apikey):
# Creates url used for JSON quote return
# Visit www.alphavantage.co to obtain a free api key
url = 'https://www.alphavantage.co/query?function=' + func + symbol + '&outputsize=compact&apikey=' + apikey;
return url;
def getLastRefreshedTimeSeries(func, symbol, apikey):
url = buildUrl(func, symbol, apikey);
req = Request(url);
# Attempt to open the URL, print errors if there are any, otherwise read results
try:
resp = urlopen(req);
content = resp.read().decode().strip();
except IOError, e:
if hasattr(e, 'code'): # HTTPError
message = 'http error code: ', e.code;
print message
elif hasattr(e, 'reason'): # URLError
message = "can't connect, reason: ", e.reason;
print message
print e;
else:
content = resp.read();
raise;
# convert from JSON data to Python dict and return to calling program
return json.loads(content);
# Iterate through symbols here:
root=moneydance.getCurrentAccountBook()
ra = root.getRootAccount()
#''' Skip imports for now
loadAccounts(ra)
x = 0
for security, sDate, acct in zip(mapCurrent, mapDates, mapAccounts):
symbol = security[0];
name = security[2];
func = 'TIME_SERIES_DAILY&symbol='
recentQuoteDate = sDate[1]; # Set recentQuoteDate to the last security updated date just in case getQuote fails
override = False; # used to add quote information even if data for date already exists
skip = False; # Set to True when data needed for update fails
try:
getQuote = getLastRefreshedTimeSeries(func, symbol, apikey);
recentQuoteDate = str(getQuote['Meta Data']['3. Last Refreshed'])[:10];
high = float(getQuote['Time Series (Daily)'][recentQuoteDate]['2. high']);
low = float(getQuote['Time Series (Daily)'][recentQuoteDate]['3. low']);
close = float(getQuote['Time Series (Daily)'][recentQuoteDate]['4. close']);
volume = long(float(getQuote['Time Series (Daily)'][recentQuoteDate]['5. volume']));
except:
print 'Security {0} ({1}): Invalid ticker symbol'.format(name,symbol);
skip = True;
# if not already updated or override has been specified AND retrieval didn't fail
if (recentQuoteDate != sDate[1] or override) and not skip:
part = recentQuoteDate.split("-");
lastRefreshDate = part[0]+part[1]+part[2];
lastRefreshDate = int(lastRefreshDate);
setPriceForSecurity(root.getCurrencies(), symbol, close, high, low, volume, lastRefreshDate);
setPriceForSecurity(root.getCurrencies(), symbol, close, high, low, volume,0);
print 'Security %s (%s): $%s - updated on %s: $%s ( H:$%s, L:%s, V:%s )'%(name,symbol,security[1],recentQuoteDate,close,high,low,volume);
skip = False;
# Update all currencies we can find with most recent currency quote
func = 'CURRENCY_EXCHANGE_RATE&to_currency=USD&from_currency='
currencylist = root.getCurrencies().getAllCurrencies()
x = True;
for currency in currencylist:
if (currency.getCurrencyType() == currency.getCurrencyType().valueOf("CURRENCY")):
symbol = currency.getIDString();
name = currency.getName();
try:
getCurrency = getLastRefreshedTimeSeries(func, symbol, apikey);
recentCurrencyDate = str(getCurrency['Realtime Currency Exchange Rate']['6. Last Refreshed'])[:10];
close = float(getCurrency['Realtime Currency Exchange Rate']['5. Exchange Rate']);
part = recentCurrencyDate.split("-");
lastRefreshDate = part[0]+part[1]+part[2];
lastRefreshDate = int(lastRefreshDate);
setPriceForCurrency(root.getCurrencies(), symbol, close, lastRefreshDate)
setPriceForCurrency(root.getCurrencies(), symbol, close, 0)
print 'Currency %s (%s) - updated on %s: $%s'%(name,symbol,recentQuoteDate,close);
except:
print 'Currency %s (%s) - Invalid currency'%(name,symbol);
time.sleep(2); # breathe...it's a free API, don't overwhelm or they'll just fail our requests