2022-09-24 v2 pre-TypeScript

This commit is contained in:
Steve 2025-01-05 18:30:06 +00:00
parent 6e1034bb5a
commit 3552246c8d
4 changed files with 136 additions and 54 deletions

View File

@ -168,6 +168,65 @@ GO
GRANT EXECUTE ON TYPE::PriceDataType TO WebApp_Role
GO
CREATE FUNCTION dbo.fn_GetExchangeRate(@Currency VARCHAR(3), @DT DATETIME)
RETURNS REAL
AS
BEGIN
DECLARE @Rate REAL
IF @Currency = 'GBp' COLLATE Latin1_General_CS_AS
BEGIN
SET @Rate = 100
END
ELSE
BEGIN
IF @Currency = 'GBP' COLLATE Latin1_General_CS_AS
BEGIN
SET @Rate = 1
END
ELSE
BEGIN
DECLARE @InstrumentID INT
SELECT @InstrumentID = InstrumentID FROM Instrument WHERE FullName = 'GBP/' + @Currency
IF @InstrumentID IS NULL
BEGIN
--Currency pair Instrument not found - return zero to indicate error
SET @Rate = 0
END
ELSE
BEGIN
--Is there a rate for this exact datetime?
SELECT @Rate = ClosePrice FROM InstrumentHistory_Intraday WHERE InstrumentID = @InstrumentID AND HistoryDT = @DT
IF @Rate IS NULL
BEGIN
--No exect match
DECLARE @StartDT DATETIME, @EndDT DATETIME, @StartRate REAL, @EndRate REAL
--@StartID INT, @EndID INT,
SELECT TOP 1 @StartDT = HistoryDT, @StartRate = ClosePrice FROM InstrumentHistory_Intraday WHERE InstrumentID = @InstrumentID AND HistoryDT < @DT ORDER BY HistoryDT DESC
SELECT TOP 1 @EndDT = HistoryDT, @EndRate = OpenPrice FROM InstrumentHistory_Intraday WHERE InstrumentID = @InstrumentID AND HistoryDT > @DT ORDER BY HistoryDT
IF @StartDT IS NOT NULL AND @EndDT IS NOT NULL
BEGIN
--Work out how far between the 2 dates our DT is, and calculate rate accordingly
DECLARE @TotalSeconds BIGINT
DECLARE @Percent REAL
SELECT @TotalSeconds = DATEDIFF(second, @StartDT, @EndDT)
SET @Percent = CONVERT(REAL, DATEDIFF(second, @StartDT, @DT)) / @TotalSeconds * 100
SET @Rate = @StartRate + ((@EndRate - @StartRate) / 100 * @Percent)
END
ELSE
BEGIN
--We don't have BOTH a start AND end price
--Return the non-NULL rate if we have one, zero otherwise
SET @Rate = COALESCE(@StartRate, @EndRate, 0)
END
END
END
END
END
RETURN @Rate
END
GO
--CREATE PROCEDURE usp_InsertInstrument (@ExchangeShortName varchar(10), @Symbol varchar(7), @FullName varchar(100))
CREATE PROCEDURE usp_InsertInstrument (@Symbol varchar(8), @FullName varchar(100))
AS
@ -629,7 +688,8 @@ BEGIN
h.PurchaseDate,
h.NoUnits,
h.PurchasePricePerUnit,
h.ActualExchangeRate,
ISNULL(h.ActualExchangeRate, dbo.fn_GetExchangeRate(i.Currency, h.PurchaseDate)) as [PurchaseExchangeRate],
h.NoUnits * h.PurchasePricePerUnit / ISNULL(h.ActualExchangeRate, dbo.fn_GetExchangeRate(i.Currency, h.PurchaseDate)) as [BookCostGBP],
h.SoldDate
FROM
Holding h

View File

@ -1,4 +1,5 @@
'use strict';
// @ts-check
'use strict';
var timespans = { oneSecond: 1000, oneMinute: 60 * 1000, oneHour: 60 * 60 * 1000, oneDay: 24 * 60 * 60 * 1000, oneWeek: 7 * 24 * 60 * 60 * 1000, oneMonth: 31 * 24 * 60 * 60 * 1000 };
var fetchIntervalDaily = 12 * timespans.oneHour;
var fetchIntervalIntraday = 4 * timespans.oneHour;
@ -507,6 +508,7 @@ function createSharesTableRow(instrument) {
if (Instrument.Holdings.length > 0) {
let totalUnits = 0;
let totalPrice = 0;
let totalPriceGBP = 0;
let noRows = 0;
let t = '<table class="miniHoldings"><tr><th>Account</th><th>Buy Date</th><th>Price</th><th>Units</th><th>Total</th></tr>';
for (let i = 0; i < Instrument.Holdings.length; i++) {
@ -515,6 +517,7 @@ function createSharesTableRow(instrument) {
noRows++;
totalUnits += h.NoUnits;
totalPrice += (h.NoUnits * h.PurchasePricePerUnit);
totalPriceGBP += h.BookCostGBP;
t += '<tr><td><span class="deletebutton" onclick="showModalDialog_SoldHolding(' + h.HoldingID + ')">&times;</span>' + h.AccountName + '</td>' +
'<td>' + new Date(h.PurchaseDate).yyyymmdd() + '</td>' +
'<td class="num">' + formatAmount(h.PurchasePricePerUnit, '', 2) + '</td>' +
@ -537,12 +540,15 @@ function createSharesTableRow(instrument) {
if (totalUnits > 0) {
Instrument.TotalUnitsHeld = totalUnits;
Instrument.TotalHoldingsCost = totalPrice;
Instrument.TotalHoldingsCostGBP = totalPriceGBP;
//Instrument.BreakevenPrice = totalPrice / totalUnits;
Instrument.BreakevenPrice = totalPrice / totalUnits;
t += '<tr><td class="no-border"></td>' +
'<td class="no-border">Total</td>' +
'<td class="num">' + formatAmount(Instrument.BreakevenPrice, '', 2) + '</td>' +
//'<td class="num">' + formatAmount(Instrument.TotalUnitsHeld, '', 0) + '</td>' +
'<td class="num">' + Instrument.TotalUnitsHeld.autoScale() + '</td>' +
//'<td class="num">' + formatAmount(Instrument.TotalHoldingsCost, '', 0) + '</td>' +
'<td class="num">' + formatAmount(Instrument.TotalHoldingsCost, '', 0) + '</td>' +
'</tr>';
}
@ -551,6 +557,7 @@ function createSharesTableRow(instrument) {
} else {
delete Instrument.TotalUnitsHeld;
delete Instrument.TotalHoldingsCost;
delete Instrument.TotalHoldingsCostGBP;
delete Instrument.BreakevenPrice;
return '';
}
@ -579,6 +586,42 @@ function createSharesTableRow(instrument) {
//'<td><div class="DayChart" id="divDayFlotChart' + dispOrder + '"></div><div class="DayChart" id="divDayChart' + dispOrder + '"></div><div class="DaySummary" id="divDaySummary' + dispOrder + '" /></td>'
};
function getCurrentValueContent(Instrument) {
let currentValue = '';
if (Instrument.CurrentPrice) {
if (Instrument.TotalUnitsHeld > 0) {
currentValue = '<div class="spacer"></div>';
//currentValue += 'Price (' + Instrument.Currency + '): ' + (Instrument.BreakevenPrice < 0.1 ? Instrument.BreakevenPrice.toPrecision(3) : Instrument.BreakevenPrice.toFixed(2)) + ' -&gt; ' + (Instrument.CurrentPrice < 0.1 ? Instrument.CurrentPrice.toPrecision(3) : Instrument.CurrentPrice.toFixed(2)) + ': ' + getProfitOrLoss(Instrument.BreakevenPrice, Instrument.CurrentPrice) + '<br>';
currentValue += 'Price (' + Instrument.Currency + '): ' + (Instrument.BreakevenPrice < 0.1 ? Instrument.BreakevenPrice.autoScale() : Instrument.BreakevenPrice.toFixed(2)) + ' -&gt; ' + (Instrument.CurrentPrice < 0.1 ? Instrument.CurrentPrice.autoScale() : Instrument.CurrentPrice.toFixed(2)) + ': ' + getProfitOrLoss(Instrument.BreakevenPrice, Instrument.CurrentPrice) + '<br>';
//currentValue += 'Value: ' + (Instrument.TotalHoldingsCost).toFixed(2) + ' -&gt; ' + (Instrument.TotalUnitsHeld * Instrument.CurrentPrice).toFixed(2) + ': ' + getProfitOrLoss(Instrument.TotalHoldingsCost, Instrument.TotalUnitsHeld * Instrument.CurrentPrice);
currentValue += 'Book Cost (GBP): ' + (Instrument.TotalHoldingsCostGBP).toFixed(2);
let exRate = Instruments.GetExchangeRate(Instrument.Currency, 'GBP');
if (exRate) {
if (Instrument.Currency != 'GBp') {
currentValue += '<br>GBP/' + Instrument.Currency + ' = ' + exRate.toFixed(4);
}
currentValue += '<div class="current-value spacer">';
//currentValue += 'Current value:<br>' + currencyFormatter.format(Instrument.TotalUnitsHeld * Instrument.CurrentPrice / exRate) + ': ' + getProfitOrLoss(Instrument.TotalHoldingsCostGBP / exRate, Instrument.TotalUnitsHeld * Instrument.CurrentPrice / exRate, 1);
currentValue += 'Current value:<br>' + currencyFormatter.format(Instrument.TotalUnitsHeld * Instrument.CurrentPrice / exRate) + ': ' + getProfitOrLoss(Instrument.TotalHoldingsCostGBP, Instrument.TotalUnitsHeld * Instrument.CurrentPrice / exRate, 1);
currentValue += '</div>';
} else {
currentValue += '<br>' + Instrument.Currency;
}
} else {
//INDEX, CURRENCY, EQUITY
if (Instrument.InstrumentType == 'CURRENCY') {
currentValue = 'Exchange Rate: ' + Instrument.CurrentPrice.toFixed(4);
} else {
if (Instrument.InstrumentType == 'CRYPTOCURRENCY' && Math.abs(Instrument.CurrentPrice) < 0.001) {
currentValue = 'Price (' + Instrument.Currency + '): ' + Instrument.CurrentPrice.toExponential();
} else {
currentValue = 'Price (' + Instrument.Currency + '): ' + Instrument.CurrentPrice.toFixed(2);
}
}
}
}
return currentValue;
}
function moveInstrumentUp(symbol) {
let i = Instruments.indexOfSymbol(symbol);
if (i > 0) {
@ -2341,40 +2384,6 @@ function getYahooIntradayData(Instrument) {
failure: function (response) { console.error("getYahooIntradayData error:"); console.info(response); }
});
}
function getCurrentValueContent(Instrument) {
let currentValue = '';
if (Instrument.CurrentPrice) {
if (Instrument.TotalUnitsHeld > 0) {
currentValue = '<div class="spacer"></div>';
//currentValue += 'Price (' + Instrument.Currency + '): ' + (Instrument.BreakevenPrice < 0.1 ? Instrument.BreakevenPrice.toPrecision(3) : Instrument.BreakevenPrice.toFixed(2)) + ' -&gt; ' + (Instrument.CurrentPrice < 0.1 ? Instrument.CurrentPrice.toPrecision(3) : Instrument.CurrentPrice.toFixed(2)) + ': ' + getProfitOrLoss(Instrument.BreakevenPrice, Instrument.CurrentPrice) + '<br>';
currentValue += 'Price (' + Instrument.Currency + '): ' + (Instrument.BreakevenPrice < 0.1 ? Instrument.BreakevenPrice.autoScale() : Instrument.BreakevenPrice.toFixed(2)) + ' -&gt; ' + (Instrument.CurrentPrice < 0.1 ? Instrument.CurrentPrice.autoScale() : Instrument.CurrentPrice.toFixed(2)) + ': ' + getProfitOrLoss(Instrument.BreakevenPrice, Instrument.CurrentPrice) + '<br>';
currentValue += 'Value: ' + (Instrument.TotalHoldingsCost).toFixed(2) + ' -&gt; ' + (Instrument.TotalUnitsHeld * Instrument.CurrentPrice).toFixed(2) + ': ' + getProfitOrLoss(Instrument.TotalHoldingsCost, Instrument.TotalUnitsHeld * Instrument.CurrentPrice);
let exRate = Instruments.GetExchangeRate(Instrument.Currency, 'GBP');
if (exRate) {
if (Instrument.Currency != 'GBp') {
currentValue += '<br>GBP/' + Instrument.Currency + ' = ' + exRate.toFixed(4);
}
currentValue += '<div class="current-value spacer">';
currentValue += 'Current value:<br>' + currencyFormatter.format(Instrument.TotalUnitsHeld * Instrument.CurrentPrice / exRate) + ': ' + getProfitOrLoss(Instrument.TotalHoldingsCost / exRate, Instrument.TotalUnitsHeld * Instrument.CurrentPrice / exRate, 1);
currentValue += '</div>';
} else {
currentValue += '<br>' + Instrument.Currency;
}
} else {
//INDEX, CURRENCY, EQUITY
if (Instrument.InstrumentType == 'CURRENCY') {
currentValue = 'Exchange Rate: ' + Instrument.CurrentPrice.toFixed(4);
} else {
if (Instrument.InstrumentType == 'CRYPTOCURRENCY' && Math.abs(Instrument.CurrentPrice) < 0.001) {
currentValue = 'Price (' + Instrument.Currency + '): ' + Instrument.CurrentPrice.toExponential();
} else {
currentValue = 'Price (' + Instrument.Currency + '): ' + Instrument.CurrentPrice.toFixed(2);
}
}
}
}
return currentValue;
}
function getYahooSingleDayData(Instrument) {
//console.info('getYahooSingleDayData: ' + Instrument.Symbol);
Instrument.lastFetchedSingleDay = new Date().getTime();
@ -2966,8 +2975,10 @@ function createHoldingsTable() {
if (h.SoldDate == null) {
aggUnits += h.NoUnits;
aggBookCost += h.NoUnits * h.PurchasePricePerUnit;
aggBookCostGBP += h.NoUnits * h.PurchasePricePerUnit / exchangeRate;
bookCostPerAccount.addCategoryAmount(h.AccountName, (h.NoUnits * h.PurchasePricePerUnit) / exchangeRate);
//aggBookCostGBP += h.NoUnits * h.PurchasePricePerUnit / exchangeRate;
aggBookCostGBP += h.BookCostGBP;
//bookCostPerAccount.addCategoryAmount(h.AccountName, (h.NoUnits * h.PurchasePricePerUnit) / exchangeRate);
bookCostPerAccount.addCategoryAmount(h.AccountName, h.BookCostGBP);
if (h.PurchaseDate < minPurchaseData) { minPurchaseData = h.PurchaseDate; }
if (h.PurchaseDate > maxPurchaseDate) { maxPurchaseDate = h.PurchaseDate; }
@ -2990,7 +3001,8 @@ function createHoldingsTable() {
aggCurrentValue = aggUnits * (i.Currency == 'GBp' ? i.CurrentPrice / 100 : i.CurrentPrice);
if (exchangeRate) {
aggCurrentValueGBP = (aggUnits * i.CurrentPrice) / exchangeRate;
aggGainGBP = ((i.CurrentPrice - aggPurchasePricePerUnit) * aggUnits) / exchangeRate;
//aggGainGBP = ((i.CurrentPrice - aggPurchasePricePerUnit) * aggUnits) / exchangeRate;
aggGainGBP = aggCurrentValueGBP - aggBookCostGBP;
aggSingleDayGainPercent = ((i.CurrentPrice / i.SingleDayPreviousClose) - 1) * 100;
aggSingleDayProfitOrLoss = aggSingleDayGainGBP < 0 ? 'loss' : 'profit';
}
@ -3013,7 +3025,8 @@ function createHoldingsTable() {
bookCostGBP: aggBookCostGBP,
currentValue: aggCurrentValue,
gain: (i.Currency == 'GBp' ? (i.CurrentPrice - aggPurchasePricePerUnit) / 100 : (i.CurrentPrice - aggPurchasePricePerUnit)) * aggUnits,
gainPercent: (i.CurrentPrice - aggPurchasePricePerUnit) / aggPurchasePricePerUnit * 100,
//gainPercent: (i.CurrentPrice - aggPurchasePricePerUnit) / aggPurchasePricePerUnit * 100,
gainPercent: aggGainGBP / aggBookCostGBP * 100,
currentValueGBP: aggCurrentValueGBP,
gainGBP: aggGainGBP,
singleDayGainGBP: aggSingleDayGainGBP,
@ -3087,10 +3100,12 @@ function createHoldingsTable() {
if (agg.noUnits > 0) {
r.push(agg);
holdingCurrencies.addHoldingCurrency(i.Currency, agg.noUnits * agg.purchasePricePerUnit);
//holdingCurrencies.addHoldingCurrency(i.Currency, agg.noUnits * agg.purchasePricePerUnit);
holdingCurrencies.addHoldingCurrency(i.Currency.toUpperCase(), agg.noUnits * agg.purchasePricePerUnit / (i.Currency == "GBp" ? 100 : 1));
if (i.CurrentPrice) {
if (agg.currentValueGBP > maxCurrentValueGBP) { maxCurrentValueGBP = agg.currentValueGBP };
holdingCurrenciesCurrentValue.addHoldingCurrency(i.Currency, agg.noUnits * i.CurrentPrice);
//holdingCurrenciesCurrentValue.addHoldingCurrency(i.Currency, agg.noUnits * i.CurrentPrice);
holdingCurrenciesCurrentValue.addHoldingCurrency(i.Currency.toUpperCase(), agg.noUnits * i.CurrentPrice / (i.Currency == "GBp" ? 100 : 1));
if (agg.currentExchangeRate) {
totalBookCostGBP += agg.bookCostGBP;
totalValueGBP += agg.currentValueGBP;
@ -3107,7 +3122,7 @@ function createHoldingsTable() {
let h = i.Holdings[hn];
if (h.SoldDate == null) {
let holdingBookCost = h.NoUnits * h.PurchasePricePerUnit;
let currentHoldingValue = h.NoUnits * (i.Currency == 'GBp' ? i.CurrentPrice / 100 : i.CurrentPrice);
let holdingCurrentValueGBP = 0,
@ -3120,7 +3135,8 @@ function createHoldingsTable() {
if (exchangeRate) {
let holdingCurrentValueGBP = (h.NoUnits * i.CurrentPrice) / exchangeRate;
let holdingGainGBP = ((i.CurrentPrice - h.PurchasePricePerUnit) * h.NoUnits) / exchangeRate;
//let holdingGainGBP = ((i.CurrentPrice - h.PurchasePricePerUnit) * h.NoUnits) / exchangeRate;
let holdingGainGBP = holdingCurrentValueGBP - h.BookCostGBP;
let singleDayGainGBP = ((i.CurrentPrice - (h.PurchaseDate > i.SingleDayStartDate ? h.PurchasePricePerUnit : i.SingleDayPreviousClose)) * h.NoUnits) / exchangeRate;
let singleDayGainPercent = ((i.CurrentPrice / i.SingleDayPreviousClose) - 1) * 100;
@ -3145,7 +3161,8 @@ function createHoldingsTable() {
bookCost: holdingBookCost,
currentValue: currentHoldingValue,
gain: (i.Currency == 'GBp' ? (i.CurrentPrice - h.PurchasePricePerUnit) / 100 : (i.CurrentPrice - h.PurchasePricePerUnit)) * h.NoUnits,
gainPercent: (i.CurrentPrice - h.PurchasePricePerUnit) / h.PurchasePricePerUnit * 100,
//gainPercent: (i.CurrentPrice - h.PurchasePricePerUnit) / h.PurchasePricePerUnit * 100,
gainPercent: holdingGainGBP / h.BookCostGBP * 100,
currentValueGBP: holdingCurrentValueGBP,
gainGBP: holdingGainGBP,
singleDayGainGBP: singleDayGainGBP,
@ -3163,7 +3180,8 @@ function createHoldingsTable() {
currentValuePerAccount.addCategoryAmount(h.AccountName, holdingCurrentValueGBP);
bookCostPerAccount.addCategoryAmount(h.AccountName, holdingBookCost / exchangeRate);
totalBookCostGBP += holdingBookCost / exchangeRate;
//totalBookCostGBP += holdingBookCost / exchangeRate;
totalBookCostGBP += holdingBookCostGBP;
totalValueGBP += holdingCurrentValueGBP;
totalGainGBP += holdingGainGBP;
todaysGainGBP += (marketIsOpen == 0 ? 0 : singleDayGainGBP);
@ -3401,19 +3419,21 @@ function createAccountsTables() {
noUnits: holding.NoUnits,
cost: holding.NoUnits * holding.PurchasePricePerUnit
}
if (exchangeRate) {
h.costGBP = h.cost / exchangeRate;
a.totalCostGBP += h.costGBP;
}
//if (exchangeRate) {
//h.costGBP = h.cost / exchangeRate;
h.costGBP = holding.BookCostGBP;
a.totalCostGBP += holding.BookCostGBP;
//}
if (instrument.CurrentPrice) {
h.currentPrice = instrument.CurrentPrice;
h.currentValue = holding.NoUnits * instrument.CurrentPrice;
h.gain = h.currentValue - h.cost;
if (exchangeRate) {
h.currentValueGBP = h.currentValue / exchangeRate;
h.gainGBP = h.gain / exchangeRate;
a.totalValueGBP += h.currentValueGBP;
//h.gainGBP = h.gain / exchangeRate;
h.gainGBP = h.currentValueGBP - h.costGBP;
a.totalGainGBP += h.gainGBP;
a.totalValueGBP += h.currentValueGBP;
}
}
a.holdings.push(h);
@ -3487,6 +3507,7 @@ function createAccountsTables() {
let h = a.holdings[hx];
accountAltRow = !accountAltRow;
let holdingProfitOrLoss = h.gain < 0 ? 'loss' : 'profit';
let holdingGBPProfitOrLoss = h.gainGBP < 0 ? 'loss' : 'profit';
accountsTables += '<tr' + (accountAltRow ? ' class="altShareRow"' : '') + '>' +
'<td>' + h.instrumentName + '</td>' +
'<td>' + h.symbol + '</td>' +
@ -3499,8 +3520,9 @@ function createAccountsTables() {
'<td class="num">' + (h.currency == 'GBp' ? formatAmount(h.currentValue / 100, 'GBP', 2) : formatAmount(h.currentValue, h.currency, 2)) + '</td>' +
'<td class="num">' + formatAmount(h.currentValueGBP, 'GBP', 2) + '</td>' +
'<td class="num ' + holdingProfitOrLoss + '">' + formatAmount(h.gain, h.currency, 2) + '</td>' +
'<td class="num ' + holdingProfitOrLoss + '">' + formatAmount(h.gainGBP, 'GBP', 2) + '</td>' +
'<td class="num ' + holdingProfitOrLoss + '">' + ((h.gain / h.cost) * 100).toFixed(1) + '%</td>' +
'<td class="num ' + holdingGBPProfitOrLoss + '">' + formatAmount(h.gainGBP, 'GBP', 2) + '</td>' +
//'<td class="num ' + holdingProfitOrLoss + '">' + ((h.gain / h.cost) * 100).toFixed(1) + '%</td>' +
'<td class="num ' + holdingGBPProfitOrLoss + '">' + ((h.gainGBP / h.costGBP) * 100).toFixed(1) + '%</td>' +
'</tr>';
}
accountsTables += '</tbody></table>';