やったこと
- スプレッドシートに営業キャッシュフローマージンを調べたい米国企業のティッカーシンボルを記入
- このティッカーシンボルをもとに、米国版yahoo financeから対応する銘柄の営業キャッシュフローと売上高をスクレイピング
- それらの比率を計算し、スプレッドシートに書き出し
最近米国株に興味が出て「MarketHack流 世界一わかりやすい米国式投資の技法」という本を読みました。
本の中に、営業キャッシュフローマージンが15〜35%ある会社を狙えと書いてありました。
営業キャッシュフローマージンの算出は、米国版yahoo financeの「financials」ページにある、"Total Cash Flow From Operating Activities"(営業キャッシュフロー)と"Total Revenue"(売上高)の比をとれば良いとのことです。
GASの勉強がてら、これをスクレイピングしてスプレッドシートに書き出すようにしてみました。
※売上高(Total Revenue)のページ。日付もこのページのRevenueの行から抜き出す。
※営業キャッシュフロー(Total Cash Flow From Operating Activities)のページ。
※日本のyahooファイナンスはスクレイピング禁止とのことですが、米国版の方をざっと見た所、そのような記述が見当たりませんでした。間違っていたらすいません。
変数名とかクラス名がアレですが、↓メインの流れ。
function my_Function(){
//スプレッドシートに記入されているティッカーを配列として取得
var sheet = SpreadsheetApp.getActiveSheet();
var ticker_array = sheet.getRange(2, 1, sheet.getLastRow()-1, 1).getValues();
//銘柄ごとに、後述のStock_itemインスタンスを作成
var output_array = [];
for(var i = 0; i<ticker_array.length; i++){
var Stock_item_1 = new Stock_item(ticker_array[i]);
//get_item_arrayメソッドを実行。items配列の要素に合致するデータをサイトから取得。メンバーのdata_arrayにpushしていく。Revenueとしているが実態は決算の日付を取得。
var items = ['Revenue','Total Revenue','Total Cash Flow From Operating Activities'];
for(var j = 0; j<items.length; j++){
Stock_item_1.get_item_array(items[j]);
};
//get_marginメソッドで営業キャッシュフローマージンを計算し、data_array配列にpush。
Stock_item_1.get_margin();
var output_array = output_array.concat(Stock_item_1.data_array);
};
//スプレッドシートに書き出し
sheet.getRange(2, 3, output_array.length, output_array[0].length).setValues(output_array);
}
コンストラクタ↓。インスタンス作成時に、プロパティにティッカーシンボルを設定。
var Stock_item = function(ticker){
this.ticker = ticker;
this.data_array =[];//空の配列。get_item_arrayメソッドで取得データをpush
};
get_item_arrayメソッド↓。銘柄ごとに、日付、売り上げ、営業キャッシュフロー(これらをitemとしました)をスクレイピングで取得し、プロパティに配列として設定。メソッドとはこんな感じで良いのでしょうか。。。
Stock_item.prototype.get_item_array = function(item){
this.item = item;
//itemによって適当なURLを設定。★要エラー処理。
var URL_base = 'https://finance.yahoo.com/quote/';
if (this.item != "Total Cash Flow From Operating Activities"){
this.URL = URL_base + this.ticker + '/financials?p=' + this.ticker;
} else {
this.URL = URL_base + this.ticker + '/cash-flow?p=' + this.ticker;
}
//HTMLを取得。目的の数字が<span>タグで囲まれていたので、これでHTML内検索。
//タグを削除した配列にし、目的の値のみ抜き出し。
var html = UrlFetchApp.fetch(this.URL).getContentText();
html = html.match(/<span data-reactid=".*?<\/span>/gi);//ここからhtmlは配列
html = html.map(function(value,index,array){
return removeTag(value);
});
var begin_index = html.indexOf(this.item);
var temp_array = html.slice(begin_index,begin_index+5);
this.data_array.push(temp_array);
};
get_marginメソッド↓。営業キャッシュフローマージンを計算してthis.data_array配列に追加する。スクレイピングした値が文字列だったので、カンマを取り除き数値に変換しています。
Stock_item.prototype.get_margin = function(){
var _ = Underscore.load();
var temp_Trans = _.zip.apply(_, this.data_array);
var i_TR = temp_Trans[0].indexOf('Total Revenue');
var i_CF = temp_Trans[0].indexOf('Total Cash Flow From Operating Activities');
var margin = ["C/F margin"];
for (var i = 1; i<5; i++){
var value_cf = parseInt(this.data_array[i_CF][i].replace(/,/g, ""),10);//カンマ取り除いて整数にする。
var value_tr = parseInt(this.data_array[i_TR][i].replace(/,/g, ""),10);
var value_margin = value_cf/value_tr;
margin.push(value_margin);
};
this.data_array.push(margin);
};
タグ削除関数↓。get_item_arrayメソッド内で、とってきたHTMLの配列の各要素からタグを削除する。
function removeTag(str){
return str.replace(/<\/?[^>]+>/gi, '');
}
実行前

実行後
出力した表のどれがどの銘柄なのかわかるようにしたり、グラフによる可視化などを今後付け加えたいです。Visaの営業キャッシュフローマージンがかなり高い。
参考にしたもの
参考になりました。
https://www.amazon.co.jp/dp/B07BNB1Z9L/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1