include dividend reinvestment in trailing returns, add price data
This commit is contained in:
parent
075f16ac52
commit
22b0d807bb
1 changed files with 57 additions and 15 deletions
72
src/main.zig
72
src/main.zig
|
|
@ -64,8 +64,13 @@ fn handleHelp(_: *App, _: *httpz.Request, res: *httpz.Response) !void {
|
||||||
\\ GET /{SYMBOL}/options Raw SRF cache file
|
\\ GET /{SYMBOL}/options Raw SRF cache file
|
||||||
\\ GET /symbols List of tracked symbols
|
\\ GET /symbols List of tracked symbols
|
||||||
\\
|
\\
|
||||||
|
\\Returns fields:
|
||||||
|
\\ trailing{1,3,5,10}YearReturn Total return with dividend reinvestment
|
||||||
|
\\ price{1,3,5,10}YearReturn Price-only return (from adjusted close)
|
||||||
|
\\ volatility 3-year annualized volatility
|
||||||
|
\\
|
||||||
\\XML example (LibreCalc):
|
\\XML example (LibreCalc):
|
||||||
\\ =FILTERXML(WEBSERVICE("http://host/AAPL/returns?fmt=xml"),"//trailing1YearReturn")
|
\\ =FILTERXML(WEBSERVICE("http://host/AAPL/returns?fmt=xml"),"//total10YearReturn")
|
||||||
\\
|
\\
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
@ -143,17 +148,42 @@ fn handleReturns(app: *App, req: *httpz.Request, res: *httpz.Response) !void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ret = zfin.performance.trailingReturns(candles);
|
// Price-only returns (from adjusted close)
|
||||||
|
const price_ret = zfin.performance.trailingReturns(candles);
|
||||||
var date_buf: [10]u8 = undefined;
|
var date_buf: [10]u8 = undefined;
|
||||||
const date_str = candles[candles.len - 1].date.format(&date_buf);
|
const date_str = candles[candles.len - 1].date.format(&date_buf);
|
||||||
const risk = zfin.risk.trailingRisk(candles);
|
const risk = zfin.risk.trailingRisk(candles);
|
||||||
|
|
||||||
const r1y = if (ret.one_year) |r| r.annualized_return else null;
|
const p1y = if (price_ret.one_year) |r| r.annualized_return else null;
|
||||||
const r3y = if (ret.three_year) |r| r.annualized_return else null;
|
const p3y = if (price_ret.three_year) |r| r.annualized_return else null;
|
||||||
const r5y = if (ret.five_year) |r| r.annualized_return else null;
|
const p5y = if (price_ret.five_year) |r| r.annualized_return else null;
|
||||||
const r10y = if (ret.ten_year) |r| r.annualized_return else null;
|
const p10y = if (price_ret.ten_year) |r| r.annualized_return else null;
|
||||||
const vol = if (risk.three_year) |r| r.volatility else null;
|
const vol = if (risk.three_year) |r| r.volatility else null;
|
||||||
|
|
||||||
|
// Total returns with dividend reinvestment (non-fatal if dividends unavailable).
|
||||||
|
// trailing* fields use total return when available, falling back to price-only.
|
||||||
|
var t1y: ?f64 = p1y;
|
||||||
|
var t3y: ?f64 = p3y;
|
||||||
|
var t5y: ?f64 = p5y;
|
||||||
|
var t10y: ?f64 = p10y;
|
||||||
|
|
||||||
|
if (app.svc.getDividends(symbol)) |div_result| {
|
||||||
|
defer zfin.Dividend.freeSlice(app.allocator, div_result.data);
|
||||||
|
const total = zfin.performance.trailingReturnsWithDividends(candles, div_result.data);
|
||||||
|
if (total.one_year) |r| {
|
||||||
|
t1y = r.annualized_return;
|
||||||
|
}
|
||||||
|
if (total.three_year) |r| {
|
||||||
|
t3y = r.annualized_return;
|
||||||
|
}
|
||||||
|
if (total.five_year) |r| {
|
||||||
|
t5y = r.annualized_return;
|
||||||
|
}
|
||||||
|
if (total.ten_year) |r| {
|
||||||
|
t10y = r.annualized_return;
|
||||||
|
}
|
||||||
|
} else |_| {}
|
||||||
|
|
||||||
// Check if XML requested
|
// Check if XML requested
|
||||||
if (q.get("fmt")) |fmt| {
|
if (q.get("fmt")) |fmt| {
|
||||||
if (std.ascii.eqlIgnoreCase(fmt, "xml")) {
|
if (std.ascii.eqlIgnoreCase(fmt, "xml")) {
|
||||||
|
|
@ -166,16 +196,24 @@ fn handleReturns(app: *App, req: *httpz.Request, res: *httpz.Response) !void {
|
||||||
\\ <trailing3YearReturn>{s}</trailing3YearReturn>
|
\\ <trailing3YearReturn>{s}</trailing3YearReturn>
|
||||||
\\ <trailing5YearReturn>{s}</trailing5YearReturn>
|
\\ <trailing5YearReturn>{s}</trailing5YearReturn>
|
||||||
\\ <trailing10YearReturn>{s}</trailing10YearReturn>
|
\\ <trailing10YearReturn>{s}</trailing10YearReturn>
|
||||||
|
\\ <price1YearReturn>{s}</price1YearReturn>
|
||||||
|
\\ <price3YearReturn>{s}</price3YearReturn>
|
||||||
|
\\ <price5YearReturn>{s}</price5YearReturn>
|
||||||
|
\\ <price10YearReturn>{s}</price10YearReturn>
|
||||||
\\ <volatility>{s}</volatility>
|
\\ <volatility>{s}</volatility>
|
||||||
\\</returns>
|
\\</returns>
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
symbol,
|
symbol,
|
||||||
date_str,
|
date_str,
|
||||||
fmtPct(arena, r1y),
|
fmtPct(arena, t1y),
|
||||||
fmtPct(arena, r3y),
|
fmtPct(arena, t3y),
|
||||||
fmtPct(arena, r5y),
|
fmtPct(arena, t5y),
|
||||||
fmtPct(arena, r10y),
|
fmtPct(arena, t10y),
|
||||||
|
fmtPct(arena, p1y),
|
||||||
|
fmtPct(arena, p3y),
|
||||||
|
fmtPct(arena, p5y),
|
||||||
|
fmtPct(arena, p10y),
|
||||||
fmtPct(arena, vol),
|
fmtPct(arena, vol),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
@ -184,14 +222,18 @@ fn handleReturns(app: *App, req: *httpz.Request, res: *httpz.Response) !void {
|
||||||
|
|
||||||
res.content_type = httpz.ContentType.JSON;
|
res.content_type = httpz.ContentType.JSON;
|
||||||
res.body = try std.fmt.allocPrint(arena,
|
res.body = try std.fmt.allocPrint(arena,
|
||||||
\\{{"ticker":"{s}","returnDate":"{s}","trailing1YearReturn":{s},"trailing3YearReturn":{s},"trailing5YearReturn":{s},"trailing10YearReturn":{s},"volatility":{s}}}
|
\\{{"ticker":"{s}","returnDate":"{s}","trailing1YearReturn":{s},"trailing3YearReturn":{s},"trailing5YearReturn":{s},"trailing10YearReturn":{s},"price1YearReturn":{s},"price3YearReturn":{s},"price5YearReturn":{s},"price10YearReturn":{s},"volatility":{s}}}
|
||||||
, .{
|
, .{
|
||||||
symbol,
|
symbol,
|
||||||
date_str,
|
date_str,
|
||||||
fmtPct(arena, r1y),
|
fmtPct(arena, t1y),
|
||||||
fmtPct(arena, r3y),
|
fmtPct(arena, t3y),
|
||||||
fmtPct(arena, r5y),
|
fmtPct(arena, t5y),
|
||||||
fmtPct(arena, r10y),
|
fmtPct(arena, t10y),
|
||||||
|
fmtPct(arena, p1y),
|
||||||
|
fmtPct(arena, p3y),
|
||||||
|
fmtPct(arena, p5y),
|
||||||
|
fmtPct(arena, p10y),
|
||||||
fmtPct(arena, vol),
|
fmtPct(arena, vol),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue