【发布时间】:2021-08-28 09:03:47
【问题描述】:
我是 google app 脚本的新手,并试图尽可能多地学习,但我偶然发现了一些我头疼的东西.....
我的目标是创建一个函数,在给定交易历史的输入数据的情况下,以“先进先出”的会计风格(即先进先出)计算股票的已实现收益。
计算已实现收益的公式相对简单
(Total Sell price - Original Cost ) = Realized gains/loss
Realized Gains/Loss / Original Cost = Profit/loss (%)
如果有人在三个不同的时间以三种不同的价格(x1、x2、x3)购买了一只股票,并且您希望计算“已实现收益” - 您是采用 x1、x2 还是 x3 的原始成本? FIFO 样式将采用 X1,因为它是“先进先出”。这很重要,因为在美国有一种基于所有已实现收益的资本利得税。
这是我的数据:https://docs.google.com/spreadsheets/d/1V7CpCxBH0lg6wi1TAhfZJP5gXE8hj7ivQ8_ULxLSLgs/edit?usp=sharing
const ss = SpreadsheetApp.getActiveSpreadsheet();
const historySheet = ss.getSheetByName('Blad1');
function fifoProject () {
let input = historySheet.getDataRange().getValues();
let onlyBuyRows = input.filter(row => row[2] == 'Buy');
let roundedTotal, priceQuantityMultiplication;
let onlyColABDF = onlyBuyRows.map(row => {
roundedTotal = Math.round(row[5] * 100) / 100;
priceQuantityMultiplication = row[3] * roundedTotal;
return [
row[0], row[1], row[3], roundedTotal, priceQuantityMultiplication
]});
let sorted = onlyColABDF.sort((a, b) => {
if (a[1] > b[1]) return 1;
if (a[1] < b[1]) return -1;
if (a[0] > b[0]) return 1;
if (a[0] < b[0]) return -1;
return 0;
});
let arrayBuyData = [];
arrayBuyData.push(sorted);
console.log(arrayBuyData);
//ss.getSheetByName('output').getRange(1, 1, sorted.length, sorted[0].length).setValues(sorted)
let input2 = historySheet.getRange(2, 1, historySheet.getLastRow() - 1, 4).getValues();
let onlySellRows = input2.filter(row => row[2] == 'Sell');
let sellTotalArray = []
let addAllSellObject = onlySellRows.reduce((acc, curr) => {
if (curr[1] in acc) {
acc[curr[1]] += curr[3]
} else {
acc[curr[1]] = curr[3]
}
return acc;
}, {});
let addAllSellArray = Object.entries(addAllSellObject).sort((a, b) => {
if (a[0] > b[0]) return 1;
if (a[0] < b[0]) return -1;
return 0;
})
sellTotalArray.push(addAllSellArray);
console.log(sellTotalArray[0][1]);
}
这是我认为该函数应该做的:
非常欢迎任何朝着正确方向提出的想法。
编辑:试图澄清这个问题。希望这样做:
<style>
.demo {
border:1px solid #C0C0C0;
border-collapse:collapse;
padding:5px;
}
.demo th {
border:1px solid #C0C0C0;
padding:5px;
background:#F0F0F0;
}
.demo td {
border:1px solid #C0C0C0;
padding:5px;
}
</style>
<table class="demo">
<caption></caption> <thead> <tr> <th>Date</th>
<th>Type</th>
<th>Amount p.p</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
<tr>
<td> Jan</td>
<td> Buy</td>
<td> $10</td>
<td> 5</td>
</tr>
<tr>
<td> Feb</td>
<td> Buy</td>
<td> $15</td>
<td> 8</td>
</tr>
</tbody>
</table>
例如,如果以 23 美元的价格售出 7 个数量,则会导致:
<style>
.demo {
border:1px solid #C0C0C0;
border-collapse:collapse;
padding:5px;
}
.demo th {
border:1px solid #C0C0C0;
padding:5px;
background:#F0F0F0;
}
.demo td {
border:1px solid #C0C0C0;
padding:5px;
}
</style>
<table class="demo">
<caption></caption> <thead> <tr> <th>Date</th>
<th>Amount</th>
<th>Buy price p.p</th>
<th>Profit p.p</th>
</tr> </thead> <tbody> <tr>
<td> Jan</td>
<td> 5</td>
<td> $10</td>
<td> $13</td>
</tr>
<tr>
<td> Feb</td>
<td> 2</td>
<td> $15</td>
<td> $8</td>
</tr>
</tbody>
</table>
总计:
<style>
.demo {
border:1px solid #C0C0C0;
border-collapse:collapse;
padding:5px;
}
.demo th {
border:1px solid #C0C0C0;
padding:5px;
background:#F0F0F0;
}
.demo td {
border:1px solid #C0C0C0;
padding:5px;
}
</style>
<table class="demo">
<caption></caption> <thead> <tr> <th><br></th>
<th><br></th>
</tr>
</thead>
<tbody>
<tr>
<td> Total buy price</td>
<td> $80</td>
</tr>
<tr>
<td> Total sell price</td>
<td> $161</td>
</tr>
<tr>
<td> Total profit (or loss)</td>
<td> $81</td>
</tr>
<tbody>
</table>
编辑 2:根据 Jacques 的回答,我创建了以下代码:
const ss = SpreadsheetApp.getActiveSpreadsheet();
const historySheet = ss.getSheetByName('Blad1');
// Function which pushes item x amount of times based on a number
function pushNumber (number, array, item) {
for(var i = 0; i<number; i++){
array.push(item);
}
}
function shiftNumber (number, array, item) {
for(var i = 0; i<number; i++){
array.shift(item);
}
}
function projectFIFO () {
let input = historySheet.getRange(3,1,historySheet.getLastRow()-1, 5).getValues();
for (var i = 0; i<security.length; i++) {
let action = row[2].toString();
let quantity = Number(row[3]);
let price = Number(row[4]);
let emptyArray = [];
// console.log(quantity);
for (security of array)
if (action === 'Buy') {
let numberPush = quantity;
pushNumber(quantity, emptyArray, price);
};
console.log(emptyArray);
};
}
基本上我已经创建了一个辅助函数 pushNumber,它根据 Number 的数量进行推送。然后在 fifo 函数中,我创建一个 for 循环来遍历每一行并查看是否有购买并根据数量推送购买,推送在一个空数组内。但是,我想学习如何为每个安全单独而不是整个范围执行此操作。我认为也许一个对象是一个解决方案,但还没有弄清楚。
【问题讨论】:
-
能否请您分解并简化您的问题?
-
@idfurw 对问题进行了编辑以试图澄清。
标签: google-apps-script stock fifo