use of name.abuchen.portfolio.util.RateLimitExceededException in project portfolio by buchen.
the class AlphavantageQuoteFeed method updateLatestQuotes.
@Override
public boolean updateLatestQuotes(Security security, List<Exception> errors) {
if (security.getTickerSymbol() == null) {
errors.add(new IOException(MessageFormat.format(Messages.MsgMissingTickerSymbol, security.getName())));
return false;
}
if (apiKey == null)
throw new IllegalArgumentException(Messages.MsgAlphaVantageAPIKeyMissing);
if (rateLimiter != null && !rateLimiter.tryAcquire())
throw new RateLimitExceededException(Messages.MsgAlphaVantageRateLimitExceeded);
String wknUrl = MessageFormat.format(// $NON-NLS-1$
"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY" + // $NON-NLS-1$
"&symbol={0}&interval=1min&apikey={1}&datatype=csv&outputsize=compact", security.getTickerSymbol(), apiKey);
try {
URL obj = new URL(wknUrl);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setConnectTimeout(1000);
con.setReadTimeout(20000);
int responseCode = con.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK)
// $NON-NLS-1$
throw new IOException(wknUrl + " --> " + responseCode);
try (Scanner scanner = new Scanner(con.getInputStream(), StandardCharsets.UTF_8.name())) {
// $NON-NLS-1$
String body = scanner.useDelimiter("\\A").next();
// $NON-NLS-1$
String[] lines = body.split("\\r?\\n");
if (lines.length <= 2)
return false;
// poor man's check
if (// $NON-NLS-1$
!"timestamp,open,high,low,close,volume".equals(lines[0])) {
errors.add(new IOException(MessageFormat.format(Messages.MsgUnexpectedHeader, body)));
return false;
}
String line = lines[1];
// $NON-NLS-1$
String[] values = line.split(",");
if (values.length != 6)
throw new IOException(MessageFormat.format(Messages.MsgUnexpectedValue, line));
// $NON-NLS-1$
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LatestSecurityPrice price = new LatestSecurityPrice();
price.setDate(LocalDate.parse(values[0], formatter));
price.setValue(asPrice(values[4]));
price.setHigh(asPrice(values[2]));
price.setLow(asPrice(values[3]));
price.setVolume(Long.parseLong(values[5]));
price.setPreviousClose(LatestSecurityPrice.NOT_AVAILABLE);
if (price.getValue() != 0)
security.setLatest(price);
return true;
}
} catch (IOException | ParseException e) {
errors.add(e);
return false;
}
}
use of name.abuchen.portfolio.util.RateLimitExceededException in project portfolio by buchen.
the class AlphavantageQuoteFeed method getHistoricalQuotes.
private <T extends SecurityPrice> List<T> getHistoricalQuotes(Class<T> klass, Security security, OutputSize outputSize, List<Exception> errors) {
if (security.getTickerSymbol() == null) {
errors.add(new IOException(MessageFormat.format(Messages.MsgMissingTickerSymbol, security.getName())));
return Collections.emptyList();
}
if (apiKey == null)
throw new IllegalArgumentException(Messages.MsgAlphaVantageAPIKeyMissing);
if (rateLimiter != null && !rateLimiter.tryAcquire())
throw new RateLimitExceededException(Messages.MsgAlphaVantageRateLimitExceeded);
String wknUrl = MessageFormat.format(// $NON-NLS-1$
"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY" + // $NON-NLS-1$
"&symbol={0}&apikey={1}&datatype=csv&outputsize={2}", security.getTickerSymbol(), apiKey, outputSize.name().toLowerCase(Locale.US));
try {
URL obj = new URL(wknUrl);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setConnectTimeout(1000);
con.setReadTimeout(20000);
int responseCode = con.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK)
// $NON-NLS-1$
throw new IOException(wknUrl + " --> " + responseCode);
try (Scanner scanner = new Scanner(con.getInputStream(), StandardCharsets.UTF_8.name())) {
// $NON-NLS-1$
String body = scanner.useDelimiter("\\A").next();
// $NON-NLS-1$
String[] lines = body.split("\\r?\\n");
if (lines.length <= 2)
return Collections.emptyList();
// poor man's check
if (// $NON-NLS-1$
!"timestamp,open,high,low,close,volume".equals(lines[0])) {
errors.add(new IOException(MessageFormat.format(Messages.MsgUnexpectedHeader, lines[0])));
return Collections.emptyList();
}
// $NON-NLS-1$
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
List<T> prices = new ArrayList<>();
for (int ii = 1; ii < lines.length; ii++) {
String line = lines[ii];
// $NON-NLS-1$
String[] values = line.split(",");
if (values.length != 6)
throw new IOException(MessageFormat.format(Messages.MsgUnexpectedValue, line));
T price = klass.newInstance();
if (values[0].length() > 10)
values[0] = values[0].substring(0, 10);
price.setDate(LocalDate.parse(values[0], formatter));
price.setValue(asPrice(values[4]));
if (price instanceof LatestSecurityPrice) {
LatestSecurityPrice lsp = (LatestSecurityPrice) price;
lsp.setHigh(asPrice(values[2]));
lsp.setLow(asPrice(values[3]));
lsp.setVolume(Long.parseLong(values[5]));
lsp.setPreviousClose(LatestSecurityPrice.NOT_AVAILABLE);
}
if (price.getValue() != 0)
prices.add(price);
}
return prices;
}
} catch (IOException | ParseException | InstantiationException | IllegalAccessException e) {
errors.add(e);
return Collections.emptyList();
}
}
use of name.abuchen.portfolio.util.RateLimitExceededException in project portfolio by buchen.
the class UpdateQuotesJob method addHistoricalQuotesJobs.
private void addHistoricalQuotesJobs(Dirtyable dirtyable, List<Job> jobs) {
// randomize list in case LRU cache size of HTMLTableQuote feed is too
// small; otherwise entries would be evicted in order
Collections.shuffle(securities);
for (Security security : securities) {
Job job = new Job(security.getName()) {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
QuoteFeed feed = Factory.getQuoteFeedProvider(security.getFeed());
if (feed == null)
return Status.OK_STATUS;
ArrayList<Exception> exceptions = new ArrayList<>();
if (feed.updateHistoricalQuotes(security, exceptions))
dirtyable.markDirty();
if (!exceptions.isEmpty())
PortfolioPlugin.log(createErrorStatus(security.getName(), exceptions));
return Status.OK_STATUS;
} catch (RateLimitExceededException e) {
schedule(2000);
return Status.OK_STATUS;
}
}
};
if (HTMLTableQuoteFeed.ID.equals(security.getFeed()))
job.setRule(HostSchedulingRule.createFor(security.getFeedURL()));
jobs.add(job);
}
}
Aggregations