前回の「[Power BI] DAXで株価のロウソク足チャートに移動平均線を描く」の続きです。DAX式が怪しいので、まだ検証中の記事です。
RANKXを使って計算する
SQLBIのビデオ「Rolling average with working days in DAX」では、最後にRANKXを使用して、以下のように移動平均線を作成しています。
SQLBI
Rolling 30WD Live =
VAR Dates =
ADDCOLUMNS (
ALL ( 'Date'[Date], 'Date'[Working Day] ),
"@Working Day Number",
RANKX (
FILTER ( ALL ( 'Date' ), 'Date'[Working Day] ),
'Date'[Date],
,
ASC
) - NOT 'Date'[Working Day]
)
VAR NumberOfDays = 30
VAR MaxDate = MAX ( 'Date'[Date] )
VAR MaxWorkingDay =
MAXX (
FILTER ( Dates, 'Date'[Date] <= MaxDate ),
[@Working Day Number]
)
VAR MinWorkingDay = MaxWorkingDay - ( NumberOfDays - 1 )
VAR MaxDateEver = CALCULATE ( MAX ( Sales[Order Date] ), REMOVEFILTERS() )
VAR DatesToUse =
FILTER (
Dates,
[@Working Day Number] >= MinWorkingDay &&
'Date'[Date] <= MaxDate
)
VAR Result =
DIVIDE (
CALCULATE ( [Sales Amount], DatesToUse, REMOVEFILTERS ( 'Date' ) ),
NumberOfDays
)
RETURN
IF ( MaxDate <= MaxDateEver, Result )
これを読み解くのは大変ですが、今回の株価のデータに合わせて作成してみたいと思います。
まず、終値の平均値を求めるメジャーを作成します。
PriceAve
PriceAve = AVERAGE(df[close])
SQLBIのデータとの違いは、SQLBIでは日付テーブルに 'Date'[Working Day] という項目が存在し、営業日はtrue、休業日はfalseが入っています。私のデータでは、日付テーブルにそのような項目を設けず、株価データが存在するかどうかで営業日かどうかを判定することにします。
RANKXを使用したバージョン
VAR Dates =
ADDCOLUMNS(
ALL( '日付テーブル'[Date] ),
"@Working Day Number",
RANKX(
FILTER( ALL( '日付テーブル' ), [PriceAve] > 0 ),
'日付テーブル'[Date],
,
ASC
) - ( SUM( df[close] ) = 0 )
)
VAR NumberOfDays = 5
VAR MaxDate = MAX( '日付テーブル'[Date] )
VAR MaxWorkingDay =
MAXX(
FILTER( Dates, '日付テーブル'[Date] <= MaxDate ),
[@Working Day Number]
)
VAR MinWorkingDay = MaxWorkingDay - ( NumberOfDays - 1 )
VAR MaxDateEver =
CALCULATE( MAX( df[date] ), REMOVEFILTERS( ) )
VAR DatesToUse =
FILTER(
Dates,
[@Working Day Number] >= MinWorkingDay
&& [Date] <= MaxDate
)
VAR Result =
CALCULATE(
[PriceAve],
DatesToUse,
REMOVEFILTERS( '日付テーブル' )
)
VAR MarketOpenDate = MAX( df[date] )
RETURN
IF( MarketOpenDate, Result )
NETWORTKDAYSを使用したバージョン
最近リリースされたNETWORKDAYSを使ってみます。日付テーブルと株価データの日付を使って休日テーブル holiday を作成し、NETWORKDAYSの引数に入れます。
NETWORKDAYSを使ったバージョン
VAR MinDateEver =
CALCULATE( MIN( df[date] ), REMOVEFILTERS( ) )
VAR MaxDate = MAX( '日付テーブル'[Date] )
VAR Dates =
ADDCOLUMNS(
ALL( '日付テーブル'[Date] ),
"@Working Day Number",
NETWORKDAYS( MinDateEver, '日付テーブル'[Date], 1, holiday )
)
VAR NumberOfDays = 5
VAR MaxWorkingDay =
MAXX(
FILTER( Dates, '日付テーブル'[Date] <= MaxDate ),
[@Working Day Number]
)
VAR MinWorkingDay = MaxWorkingDay - ( NumberOfDays - 1 )
VAR MaxDateEver =
CALCULATE( MAX( df[date] ), REMOVEFILTERS( ) )
VAR DatesToUse =
FILTER(
Dates,
[@Working Day Number] >= MinWorkingDay
&& [Date] <= MaxDate
)
VAR Result =
CALCULATE(
[PriceAve],
DatesToUse,
REMOVEFILTERS( '日付テーブル' )
)
VAR MarketOpenDate = MAX( df[date] )
RETURN
IF( MarketOpenDate, Result )