Skip to content

Commit

Permalink
Added quote feed for AMFI India
Browse files Browse the repository at this point in the history
  • Loading branch information
buchen committed Sep 8, 2024
1 parent ae3788e commit 07ba68e
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name.abuchen.portfolio.online.impl.ManualQuoteFeed
name.abuchen.portfolio.online.impl.AlphavantageQuoteFeed
name.abuchen.portfolio.online.impl.AMFIIndiaQuoteFeed
name.abuchen.portfolio.online.impl.BitfinexQuoteFeed
name.abuchen.portfolio.online.impl.BinanceQuoteFeed
name.abuchen.portfolio.online.impl.CoinGeckoQuoteFeed
Expand All @@ -12,8 +13,8 @@ name.abuchen.portfolio.online.impl.LeewayQuoteFeed
name.abuchen.portfolio.online.impl.TwelveDataQuoteFeed
name.abuchen.portfolio.online.impl.PortfolioReportQuoteFeed
name.abuchen.portfolio.online.impl.QuandlQuoteFeed
name.abuchen.portfolio.online.impl.HTMLTableQuoteFeed
name.abuchen.portfolio.online.impl.CSQuoteFeed
name.abuchen.portfolio.online.impl.YahooFinanceQuoteFeed
name.abuchen.portfolio.online.impl.YahooFinanceAdjustedCloseQuoteFeed
name.abuchen.portfolio.online.impl.HTMLTableQuoteFeed
name.abuchen.portfolio.online.impl.GenericJSONQuoteFeed
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ public class Messages extends NLS
public static String MsgErrorInvestmentPlanMissingSecurityPricesToGenerateTransaction;
public static String MsgErrorLeewayAPIKeyMissing;
public static String MsgErrorMissingAPIKey;
public static String MsgErrorMissingIdentifierForSecurity;
public static String MsgErrorMissingKeyValueInJSON;
public static String MsgErrorMissingOnlineId;
public static String MsgErrorMissingPathToDateOrClose;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ MsgErrorLeewayAPIKeyMissing = PWP Leeway UG API key is missing. Configure in pre

MsgErrorMissingAPIKey = API key is missing. Configure API key in preferences.

MsgErrorMissingIdentifierForSecurity = Missing identifier {0} for instrument {1}

MsgErrorMissingKeyValueInJSON = Missing value for key ''{0}''

MsgErrorMissingOnlineId = Missing Portfolio Report OnlineId for security {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ MsgErrorLeewayAPIKeyMissing = PWP Leeway UG API key is missing. Nastavte v p\u01

MsgErrorMissingAPIKey = Chyb\u00ED kl\u00ED\u010D API. Nastavte kl\u00ED\u010D API v p\u0159edvolb\u00E1ch.

MsgErrorMissingIdentifierForSecurity = Chyb\u011Bj\u00EDc\u00ED identifik\u00E1tor {0} pro p\u0159\u00EDstroj {1}

MsgErrorMissingKeyValueInJSON = Chyb\u011Bj\u00EDc\u00ED hodnota pro kl\u00ED\u010D ''{0}''

MsgErrorMissingOnlineId = Chyb\u00ED zpr\u00E1va o portfoliu OnlineId pro cenn\u00FD pap\u00EDr {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = PWP Leeway UG API-n\u00F8gle mangler. Konfigurer i

MsgErrorMissingAPIKey = API-n\u00F8gle mangler. Konfigurer API-n\u00F8gle i pr\u00E6ferencer.

MsgErrorMissingIdentifierForSecurity = Manglende identifikation {0} for instrument {1}.

MsgErrorMissingKeyValueInJSON = Manglende v\u00E6rdi for n\u00F8gle ''{0}''

MsgErrorMissingOnlineId = Manglende online portef\u00F8ljerapport for v\u00E6rdipapir {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ MsgErrorLeewayAPIKeyMissing = PWP Leeway UG API-Schl\u00FCssel ist nicht in den

MsgErrorMissingAPIKey = API-Schl\u00FCssel fehlt. Konfigurieren Sie den API-Schl\u00FCssel in den Einstellungen.

MsgErrorMissingIdentifierForSecurity = Fehlender Bezeichner {0} f\u00FCr Instrument {1}

MsgErrorMissingKeyValueInJSON = Schl\u00FCssel ''{0}'' nicht gefunden

MsgErrorMissingOnlineId = Fehlende Portfolio Report OnlineId f\u00FCr Wertpapier {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ MsgErrorLeewayAPIKeyMissing = No hay clave API definida para PWP Leeway UG, conf

MsgErrorMissingAPIKey = Falta la clave API. Config\u00FArela en el men\u00FA 'Preferencias'.

MsgErrorMissingIdentifierForSecurity = Falta identificador {0} para instrumento {1}

MsgErrorMissingKeyValueInJSON = No se ha encontrado la clave \u201B{0}\u2019

MsgErrorMissingOnlineId = Falta Portfolio Report OnlineId para el valor {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ MsgErrorLeewayAPIKeyMissing = Clef API PWP Leeway UG manquante. \u00C0 configure

MsgErrorMissingAPIKey = La cl\u00E9 API est manquante. Configurez la cl\u00E9 API dans les pr\u00E9f\u00E9rences.

MsgErrorMissingIdentifierForSecurity = Identifiant manquant {0} pour l'instrument {1}

MsgErrorMissingKeyValueInJSON = Valeur manquante pour clef ''{0}''

MsgErrorMissingOnlineId = Portfolio Report OnlineId manquant pour titre {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = La chiave API di PWP Leeway UG \u00E8 assente. Con
MsgErrorMissingAPIKey = Manca la chiave API. Configura la chiave API nelle preferenze.
MsgErrorMissingIdentifierForSecurity = Identificatore mancante {0} per lo strumento {1}
MsgErrorMissingKeyValueInJSON = Valore mancante per la chiave ''{0}''
MsgErrorMissingOnlineId = Report Portfolio, manca OnlineID del titolo {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,8 @@ MsgErrorLeewayAPIKeyMissing = De PWP Leeway UG API-sleutel ontbreekt. Configuree

MsgErrorMissingAPIKey = De API-sleutel ontbreekt. Configureer deze in Help/Instellingen/API-sleutels.

MsgErrorMissingIdentifierForSecurity = Identificatiecode {0} voor instrument {1} ontbreekt.

MsgErrorMissingKeyValueInJSON = Ontbrekende waarde voor sleutel ''{0}''

MsgErrorMissingOnlineId = Ontbrekend Portfolio Report OnlineID voor effect {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = Brak klucza API PWP Leeway UG. Skonfiguruj w prefe

MsgErrorMissingAPIKey = Brakuje klucza API. Skonfiguruj klucz API w ustawieniach.

MsgErrorMissingIdentifierForSecurity = Brakuj\u0105cy identyfikator {0} dla instrumentu {1}

MsgErrorMissingKeyValueInJSON = Brakuj\u0105ca warto\u015B\u0107 dla klucza ''{0}''

MsgErrorMissingOnlineId = Brakuj\u0105cy identyfikator online raportu portfela dla waloru {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ MsgErrorLeewayAPIKeyMissing = A chave da API PWP Leeway UG est\u00E1 ausente. Co

MsgErrorMissingAPIKey = Falta a chave API. Configure a chave API nas prefer\u00EAncias.

MsgErrorMissingIdentifierForSecurity = Identificador {0} em falta para o instrumento {1}

MsgErrorMissingKeyValueInJSON = Valor ausente para a chave ''{0}''

MsgErrorMissingOnlineId = Falta Portfolio Report OnlineId para o ativo {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = A chave da API PWP Leeway UG est\u00E1 ausente. Co

MsgErrorMissingAPIKey = Falta a chave API. Configure a chave API nas prefer\u00EAncias.

MsgErrorMissingIdentifierForSecurity = Falta o identificador {0} para o instrumento {1}

MsgErrorMissingKeyValueInJSON = Valor ausente para a chave ''{0}''

MsgErrorMissingOnlineId = Falta Portfolio Report OnlineId para o ativo {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = PWP Leeway UG API key \u043E\u0442\u0441\u0443\u04

MsgErrorMissingAPIKey = \u041A\u043B\u044E\u0447 API \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442. \u041D\u0430\u0441\u0442\u0440\u043E\u0439\u0442\u0435 \u043A\u043B\u044E\u0447 API \u0432 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430\u0445.

MsgErrorMissingIdentifierForSecurity = \u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 {0} \u0434\u043B\u044F \u043F\u0440\u0438\u0431\u043E\u0440\u0430 {1}

MsgErrorMissingKeyValueInJSON = \u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043A\u043B\u044E\u0447\u0430 "{0}"

MsgErrorMissingOnlineId = \u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043E\u043D\u043B\u0430\u0439\u043D-\u0438\u0434\u0435\u043D\u0442\u0438\u0444\u0438\u043A\u0430\u0442\u043E\u0440 \u043E\u0442\u0447\u0435\u0442\u0430 \u043E \u043F\u043E\u0440\u0442\u0444\u0435\u043B\u0435 \u0434\u043B\u044F \u0430\u043A\u0442\u0438\u0432\u0430 {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = Ch\u00FDba k\u013E\u00FA\u010D API PWP Leeway UG.

MsgErrorMissingAPIKey = Ch\u00FDba k\u013E\u00FA\u010D API. Nakonfigurujte k\u013E\u00FA\u010D API v nastaveniach.

MsgErrorMissingIdentifierForSecurity = Ch\u00FDbaj\u00FAci identifik\u00E1tor {0} pre pr\u00EDstroj {1}

MsgErrorMissingKeyValueInJSON = Ch\u00FDbaj\u00FAca hodnota pre k\u013E\u00FA\u010D ''{0}''

MsgErrorMissingOnlineId = Ch\u00FDba spr\u00E1va o portf\u00F3liu OnlineId pre cenn\u00FD papier {0}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = \u7F3A\u5C11 PWP Leeway UG API \u5BC6\u94A5\u3002\

MsgErrorMissingAPIKey = \u7F3A\u5C11 API \u5BC6\u94A5\u3002\u8BF7\u4E8E\u504F\u597D\u8BBE\u7F6E\u4E2D\u8BBE\u7F6E API \u5BC6\u94A5\u3002

MsgErrorMissingIdentifierForSecurity = \u4EEA\u5668 {1} \u7F3A\u5C11\u6807\u8BC6\u7B26 {0}

MsgErrorMissingKeyValueInJSON = \u952E \u201C{0}\u201D \u7F3A\u5C11\u503C

MsgErrorMissingOnlineId = \u8BC1\u5238 {0} \u7F3A\u5C11 Portfolio Report OnlineId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,8 @@ MsgErrorLeewayAPIKeyMissing = PWP Leeway\u7684UG API\u91D1\u9470\u4E1F\u5931\u30

MsgErrorMissingAPIKey = API\u91D1\u9470\u4E1F\u5931\u3002\u5728\u504F\u597D\u8A2D\u5B9A\u4E2D\u8A2D\u7F6EAPI\u91D1\u9470\u3002

MsgErrorMissingIdentifierForSecurity = \u5100\u5668 {1} \u7F3A\u5C11\u8B58\u5225\u78BC {0}

MsgErrorMissingKeyValueInJSON = \u9375\u503C\u300C{0}\u300D\u7F3A\u5C11\u503C

MsgErrorMissingOnlineId = \u7F3A\u5C11\u8B49\u5238{0}\u7684\u6295\u8CC7\u5831\u544A\u7DDA\u4E0AID
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package name.abuchen.portfolio.online.impl;

import java.io.IOException;
import java.text.MessageFormat;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;

import name.abuchen.portfolio.Messages;
import name.abuchen.portfolio.PortfolioLog;
import name.abuchen.portfolio.model.LatestSecurityPrice;
import name.abuchen.portfolio.model.Security;
import name.abuchen.portfolio.model.SecurityPrice;
import name.abuchen.portfolio.online.QuoteFeed;
import name.abuchen.portfolio.online.QuoteFeedData;
import name.abuchen.portfolio.util.WebAccess;

/**
* Load NAV prices from AMFI India.
*/
public class AMFIIndiaQuoteFeed implements QuoteFeed
{
private record MutualFund(String schemeCode, String isin1, String isin2, LatestSecurityPrice price)
{
}

public static final String ID = "AMFIINDIA"; //$NON-NLS-1$

private final PageCache<List<MutualFund>> cache = new PageCache<>();

@Override
public String getId()
{
return ID;
}

@Override
public String getName()
{
return "AMFI India"; //$NON-NLS-1$
}

@Override
public Optional<LatestSecurityPrice> getLatestQuote(Security security)
{
QuoteFeedData data = getHistoricalQuotes(security, false);

if (!data.getErrors().isEmpty())
PortfolioLog.abbreviated(data.getErrors());

List<LatestSecurityPrice> prices = data.getLatestPrices();

if (prices.isEmpty())
return Optional.empty();

Collections.sort(prices, new SecurityPrice.ByDate());

return Optional.of(prices.get(prices.size() - 1));
}

@Override
public QuoteFeedData previewHistoricalQuotes(Security security)
{
return getHistoricalQuotes(security, true);
}

@Override
public QuoteFeedData getHistoricalQuotes(Security security, boolean collectRawResponse)
{
if (security.getIsin() == null)
{
return QuoteFeedData.withError(
new IOException(MessageFormat.format(Messages.MsgErrorMissingIdentifierForSecurity,
Messages.CSVColumn_ISIN, security.getName())));
}

QuoteFeedData data = new QuoteFeedData();

try
{
var funds = cache.lookup(AMFIIndiaQuoteFeed.class.toString());

if (funds == null)
{
WebAccess webaccess = new WebAccess("www.amfiindia.com", "/spages/NAVAll.txt"); //$NON-NLS-1$ //$NON-NLS-2$
String content = webaccess.get();

if (collectRawResponse)
data.addResponse("https://www.amfiindia.com/spages/NAVAll.txt", content); //$NON-NLS-1$

funds = parse(content);
cache.put(AMFIIndiaQuoteFeed.class.toString(), funds);
}

for (MutualFund fund : funds)
{
if (security.getIsin().equals(fund.isin1) || security.getIsin().equals(fund.isin2))
{
data.addPrice(fund.price);
break;
}
}
}
catch (IOException e)
{
data.addError(e);
}

return data;
}

private List<MutualFund> parse(String content)
{
var answer = new ArrayList<MutualFund>();

String[] lines = content.split("\\r?\\n"); //$NON-NLS-1$

var dateFormat = DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.US); //$NON-NLS-1$

for (String line : lines)
{
// @formatter:off
// Scheme Code;ISIN Div Payout/ ISIN Growth;ISIN Div Reinvestment;Scheme Name;Net Asset Value;Date
// @formatter:on
String[] words = line.split(";"); //$NON-NLS-1$
if (words.length < 6)
continue;

String schemeCode = words[0];
String isin1 = words[1];
String isin2 = words[2];
String nav = words[4];
String date = words[5];

try
{
var price = new LatestSecurityPrice(LocalDate.parse(date, dateFormat), YahooHelper.asPrice(nav));
price.setHigh(LatestSecurityPrice.NOT_AVAILABLE);
price.setLow(LatestSecurityPrice.NOT_AVAILABLE);
price.setVolume(LatestSecurityPrice.NOT_AVAILABLE);

if (price.getValue() > 0)
answer.add(new MutualFund(schemeCode, isin1, isin2, price));
}
catch (ParseException | DateTimeParseException ignore)
{
// ignore this record
}
}

return answer;
}
}

0 comments on commit 07ba68e

Please sign in to comment.