見出し画像

キャッシュフロー

ランダムウォーカーさんのツイートを見てCF気にする人もいるのかなと思い
自分の使ってるものを紹介します

任意の新しいインジケータを作成します
既存のインジケータのCFと現金・現金同等物をくっつけて
計算でフリーCFを、CSVファイルから有利子負債を追加して1つにしています

レーダースクリーンに表示出来るインジケータ数はMAX30なので
既存のCF、現金・現金同等物、有利子負債と3つ使うより少なく
使用個数に余裕ができ、連結/単独の入力も1回で済みます

※ 有利子負債のCSVは別途用意して下さい
  必要なければプログラムをコメントかプロット時に非表示で!

プログラム

using tsdata.marketdata;
using elsystem.io;
using tsdata.common;
using elsystem;
inputs:															//任意の場所、ファイル名でOK
	FileName("C:\Program Files (x86)\TradeStation 9.5\japan-all-stock-financial-results.csv"),
	int MonthsReported( 12) [DisplayName = "MonthsReported", ToolTip = 
	 "Enter the number of months in the reporting period for which data is desired.  Fundamental data usually covers a 3, 6 or 12 month period."],
	int ConsolidationLevel( 1) [DisplayName = "ConsolidationLevel", ToolTip = 
	 "Enter 1 if consolidated data is desired; enter any other value for non-consolidated data."],
	int AccountingStandard( 0) [DisplayName = "AccountingStandard", ToolTip = 
	 "Enter 1 for Japanese accounting standard; enter 2 for Securities and Exchange Commission (SEC) accounting standard; enter 3 for International Financial Reporting Standards (IFRS) accounting standard; enter 0 to use IFRS, SEC, or Japanese accounting standards, in that order, depending on which is available."],
	PlotOpCF( 1) [DisplayName = "PlotOpCF", ToolTip = 
	 "Enter 1 to plot the company's cash flow from operations; enter a value other than 1 if it is desired not to plot this value."],
	PlotInvestCF( 1) [DisplayName = "PlotInvestCF", ToolTip = 
	 "Enter 1 to plot the company's cash flow from investing activities; enter a value other than 1 if it is desired not to plot this value."],
	PlotFinanCF( 1) [DisplayName = "PlotFinanCF", ToolTip = 
	 "Enter 1 to plot the company's cash flow from financial activities; enter a value other than 1 if it is desired not to plot this value."];
variables:
	string MyCode( "" ),
	double MyValue( 0 ),
	string Code4( "" ),
	StreamReader SR( NULL ),									//ファイルから文字を読取るクラスを実装、書き込み例については「StreamWriter」を参照
	TokenList TL( NULL ),										//フィールド名のリスト(トークンリスト)に基づいてコレクションを作成する基本クラス
	FundamentalQuotesProvider FQP( NULL ),
	intrabarpersist bool OkayToPlotOpCF( false ),				//営業CF
	intrabarpersist bool OkayToPlotInvestCF( false ),			//投資CF
	intrabarpersist bool OkayToPlotFinanCF( false ),			//財務CF
	intrabarpersist bool OkayToPlotCash( false ),				//現金等
	intrabarpersist string ConsLevel( "Consolidated" ),			//連単
	intrabarpersist string AcctStdInputString( "" ),			//会計基準
	double CROpCF( 0 ),											//営業CF
	double CRICF( 0 ),											//投資CF
	double CRFCF( 0 ),											//財務CF
	double CRCashOrCashEquivalents( 0 );						//現金等
constants:
	string MonthsReportedKey( "MonthsReported" ),
	string ConsolidatedKey( "ConsolidationLevel" ),
	string AccountingKey( "AccountingStandard" ),
	string OpCFFieldName( "CR_OpCF" ),							//営業CF
	string InvestCFFieldName( "CR_ICF" ),						//投資CF
	string FinanCFFieldName( "CR_FCF" ),						//財務CF
	string CashEqFieldName( "CR_Cash_or_Cash_Equivalents" ),	//現金等
	string ConsolidatedValue( "Consolidated" ),					//連結
	string NonConsolidatedValue( "NonConsolidated" ),			//単独
	string IFRSString( "IFRS" ),
	string SECString( "SEC" ),
	string JSTDString( "JSTD" );
	
method void CreateFundamentalQuotesProvider()
begin
	FQP = new FundamentalQuotesProvider();
	FQP.Symbol = Symbol;
	FQP.Fields += OpCFFieldName;
	FQP.Fields += InvestCFFieldName;
	FQP.Fields += FinanCFFieldName;
	FQP.Fields += CashEqFieldName;
	FQP.Realtime = false;
	FQP.TimeZone = tsdata.common.TimeZone.local;
	FQP.LoadProvider();
	Value99 = FQP.Count; { force provider to load }
end;
method bool DataHasPostDate( FundamentalQuote fq )
variables:  int Counter, DateTime MissingDT, int NumMissingDates;
begin
	NumMissingDates = 0;
	MissingDT = DateTime.Create( 1999, 11, 30 );
	for Counter = 0 to fq.Count - 1 begin
		if fq.PostDate[Counter] = MissingDT then
			NumMissingDates += 1;
	end;
	return NumMissingDates <> fq.Count;
end; { DataHasPostDate method }
method string GetAcctStdString()
variables:  string AcctStdString;
begin
	switch ( AccountingStandard )
	begin
		case 1: { JSTD }
			AcctStdString = JSTDString;
		case 2: { SEC }
			AcctStdString = SECString;
		case 3: { IFRS }
			AcctStdString = IFRSString;
	end;
	return AcctStdString;
end;
method bool GetQuoteAsOfDate( FundamentalQuote fq, DateTime tempdt, 
out double QuoteVal )
variables:  
	int Counter,
	bool QuoteFound, 
	DateTime LastDateTime,  
	string AcctStd, 
	string LastUsedAcctStd, 
	bool SetVariable,
	DateTime fqDateTime;
begin
	if fq = NULL or tempdt = NULL then return false;
	QuoteFound = false;
	LastDateTime = DateTime.Create( 1900, 1, 1 );
	SetVariable = false;
	for Counter = fq.Count - 1 downto 0 begin
		SetVariable = false;
		AcctStd = fq.ExtendedProperties[Counter][AccountingKey].StringValue;
		if fq.ExtendedProperties[Counter][MonthsReportedKey].IntegerValue = MonthsReported
			and fq.ExtendedProperties[Counter][ConsolidatedKey].StringValue	= ConsLevel
			and ( AccountingStandard = 0 or AcctStd = AcctStdInputString ) then begin
			fqDateTime = fq.PostDate[Counter];
			if tempdt >= fqDateTime and fqDateTime >= LastDateTime then begin
				if fqDateTime <> LastDateTime then begin { new PostDate }
					SetVariable = true;
				end else if AccountingStandard = 0 then begin { use hierarchy }
					if AcctStd = IFRSString then begin
						SetVariable = true;
					end else if AcctStd = SECString and LastUsedAcctStd <> IFRSString then begin
						SetVariable = true;
					end else if AcctStd = JSTDString 
						and LastUsedAcctStd <> IFRSString 
						and LastUsedAcctStd <> SECString then begin
						SetVariable = true;
					end;				
				end;	
			end;		
		end;	
		if SetVariable then begin
			QuoteVal = fq.DoubleValue[Counter];
			LastUsedAcctStd = AcctStd;
			LastDateTime = fqDateTime;
			QuoteFound = true;
		end;
	end;
	return QuoteFound;
end;{ GetQuoteAsOfDate method }
once begin
	if ConsolidationLevel = 1 then ConsLevel = ConsolidatedValue
	else ConsLevel = NonConsolidatedValue;
		
	AcctStdInputString = GetAcctStdString();
	CreateFundamentalQuotesProvider();
	
	OkayToPlotOpCF = FQP.HasQuoteData( OpCFFieldName )
	 and DataHasPostDate( FQP[OpCFFieldName] ) 
	 and PlotOpCF = 1;
	
	OkayToPlotInvestCF = FQP.HasQuoteData( InvestCFFieldName )
	 and DataHasPostDate( FQP[InvestCFFieldName] ) 
	 and PlotInvestCF = 1;
	 
	OkayToPlotFinanCF = FQP.HasQuoteData( FinanCFFieldName )
	 and DataHasPostDate( FQP[FinanCFFieldName] ) 
	 and PlotFinanCF = 1;
	 
	OkayToPlotCash = FQP.HasQuoteData( CashEqFieldName )
	 and DataHasPostDate( FQP[CashEqFieldName] );
	try SR = StreamReader.create(FileName);						//例外の発生をテストする為に使用(読取るファイルの完全パスを指定して新規インスタンスを初期化)
	catch (FileNotFoundException ex)							//指定された例外に対応して、追加コードを実行するために使用
	throw ex.create( "ファイルが見つかりません");						//イベントログに表示される例外のインスタンスを作成するために使用
	end;{ try }
	Code4 = symbol.Substring(0,4);								//エクセル側が4桁コードなのでシンボルコードから4桁だけ抜き出す
end;{ once }
if OkayToPlotOpCF and GetQuoteAsOfDate( FQP[OpCFFieldName], BarDateTime, CROpCF ) then
	Plot1( CROpCF, !( "営業CF" ) );
if OkayToPlotInvestCF and GetQuoteAsOfDate( FQP[InvestCFFieldName], BarDateTime, CRICF ) then
	Plot2( CRICF, !( "投資CF" ) );
if OkayToPlotFinanCF and GetQuoteAsOfDate( FQP[FinanCFFieldName], BarDateTime, CRFCF ) then
	Plot3( CRFCF, !( "財務CF" ) );
if OkayToPlotOpCF and OkayToPlotInvestCF then
	Plot4(( Plot1 + Plot2 ), !( "フリーCF" ) );
if OkayToPlotCash and GetQuoteAsOfDate( FQP[CashEqFieldName], BarDateTime, CRCashOrCashEquivalents ) then
	Plot5( CRCashOrCashEquivalents, !( "現金等" ) );
while Code4 <> MyCode and SR.EndOfStream = false begin			//現在のファイル位置がファイルの末尾かどうかを示す値を取得
	TL = TokenList.Create( SR.ReadLine());						//クラスの新規インスタンスを指定名に対して初期化(ファイルから文字の行を読取り)
	if TL[0] = Code4 then begin
		MyCode = TL[0];
		if TL[1] <> "-" then MyValue = Double.Parse( TL[1] );	//CSVで読み込んだ値はstring型になるので、数値のDouble型に変換
		Plot6( MyValue, !("有利子負債") );						//ハイフンを数値に変えるとエラー表示になるので除外
	end;
end;{ while }
SR.Close();														//StreamReaderオブジェクトを閉じ、リーダーに関連付けられたシステムリソースを解放

サポートされると喜んでアイスを買っちゃいます!٩(๑❛ᴗ❛๑)۶