Last active
January 25, 2024 11:21
-
-
Save kazuhito-m/354501a372a796812fdbf8bfb9a9ec5e to your computer and use it in GitHub Desktop.
AlertStockQuotations.gs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 設定した前週比の下落幅パーセントを下回った場合、チャットにアラートするGASスクリプト。 | |
* | |
* 決まった形式のGoogleSpreadSheetの情報を元に、指定銘柄の前週比(スケジューリングで一週間ごとに実行)を記録、 | |
* 指定した比率以下に下落した場合、Discordのチャンネルに通知する。 | |
* | |
* 環境変数(スクリプトプロパティに設定する) | |
* - SPREAD_SHEET_URL: データ&設定を仕込んだGoogleSpreadSheetのURL | |
* - DISCORD_ENDPOINT: Discordの特定チャンネルへのWebHook URL | |
*/ | |
function main() { | |
const spreadSheetUrl = getPropertyOf('SPREAD_SHEET_URL'); | |
const spreadSheet = SpreadsheetApp.openByUrl(spreadSheetUrl); | |
for (let sheet of spreadSheet.getSheets()) { | |
recordNowStockPrice(sheet); | |
} | |
for (let sheet of spreadSheet.getSheets()) { | |
alertDownStockPrice(sheet); | |
} | |
} | |
function recordNowStockPrice(sheet) { | |
const code = sheet.getRange('B2').getValue(); | |
const stockPrice = getGoogleFinanceNowPriceOf(code); | |
const row = findNextDataRow(sheet); | |
sheet.getRange('A' + row).setValue(new Date()); | |
sheet.getRange('B' + row).setValue(stockPrice); | |
} | |
function getGoogleFinanceNowPriceOf(googleFinanceCode) { | |
const url = `https://www.google.com/finance/quote/${googleFinanceCode}`; | |
const html = UrlFetchApp.fetch(url).getContentText(); | |
const stockPrice = Parser.data(html) | |
.from('<div class="YMlKec fxKbKc">') | |
.to('</div>') | |
.build(); | |
return stockPrice; | |
} | |
function alertDownStockPrice(sheet) { | |
const alertDownParcentages = sheet.getRange('F2').getValue() | |
.toString().split(','); | |
const lastDataRow = findNextDataRow(sheet) - 1; | |
const profitAndLossRatio = sheet.getRange('D' + lastDataRow).getValue(); | |
for (let parcent of alertDownParcentages) { | |
const alertDownRatio = parcent / -100; | |
if (profitAndLossRatio < alertDownRatio) { | |
sendAlert(sheet.getName(), parcent, profitAndLossRatio * 100); | |
break; | |
} | |
} | |
} | |
function sendAlert(name, downBaseParcent, profitAndLossParcent) { | |
console.log(name + ':' + downBaseParcent + '% , ' + profitAndLossParcent + '%'); | |
sendAlertDiscord(name, downBaseParcent, profitAndLossParcent); | |
} | |
function sendAlertDiscord(name, downBaseParcent, profitAndLossParcent) { | |
const lossParcent = Math.round(profitAndLossParcent * 100) / 100; | |
const body = `{ | |
"embeds": [ | |
{ | |
"color": 16711680, | |
"title": "株価暴落アラート", | |
"description": "\`${name}\` に、前週比 \`${downBaseParcent}%\` 以上の下落が検知されました。", | |
"fields": [ | |
{ | |
"name": "銘柄", | |
"value": "\`${name}\`", | |
"inline": false | |
}, | |
{ | |
"name": "実際の下落率", | |
"value": "\`${lossParcent}\` %", | |
"inline": false | |
} | |
] | |
} | |
] | |
}`; | |
sendDiscordMessage(body); | |
} | |
function sendDiscordMessage(bodyJson) { | |
const endPont = getPropertyOf('DISCORD_ENDPOINT'); | |
const headers = { | |
'Content-type': 'application/json', | |
}; | |
const options = { | |
'method': 'POST', | |
'headers': headers, | |
'payload': bodyJson | |
}; | |
UrlFetchApp.fetch(endPont, options); | |
} | |
function findNextDataRow(sheet) { | |
const endRow = sheet.getLastRow(); | |
for (let i = 5; i <= endRow; i++) { | |
const text = sheet.getRange('A' + i).getValue().toString(); | |
if (text.trim() === '') return i; | |
} | |
return endRow; | |
} | |
function getPropertyOf(id) { | |
return PropertiesService.getScriptProperties().getProperty(id); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment