TradingView:インジケーターのPineスクリプトまとめ

Posted on January 31st, 2019Updated on November 13th, 2023
TradingView:インジケーターのPineスクリプトまとめ

どんな記事

TradingView(トレーディングビュー)の Pineスクリプトでつくるインジケーターのメモです。どれもコピペで機能をつけ加えることができる簡単なものです。

今後も、思いついたものや見つけたものがあれば、どんどん加えていく予定です!

記事の更新

2023年11月13日
新しいサンプルの追加、既存のサンプルの一部を最適化、目次の整理を行いました。

2021年11月13日
「配列を使う」を追加し、いくつかの簡単なサンプルを削除しました。

2020年6月18日
「timezoneと夏時間の認識」の最適化を行いました。

2019年8月17日
timezone label lineに関するコードを追加しました。その他、version4の公開に伴い加筆修正を行いました。

2019年6月8日
「VWAPの累積平均を算出」を追加しました。

2019年5月4日
「チャート以外の価格データを取得」のコードを最新のものに更新、「Quandlから金融データを取得」を追加しました。

Pineスクリプトの優位性

数年前に比べると、Pineスクリプトでできることが格段に増えています。

最高なのは、四本値以外のあらゆるデータが取得できること。銘柄やタイムフレーム、データの壁がどんどんなくなっています。そして、それをどんどん自由に表現できるようになっています。

MQLやPythonがまだ優位なのは、次のような点なのかなと思います。

  • 計算速度
  • Seriesデータの閲覧性(※)
  • 機械学習
  • 統計処理
※ 時系列を自由に進んだり戻ったりしながら計算できます

時間に関するもの

Pineスクリプトは時系列について非常に厳格です。リペイント等で誤解が生じにくくなるように設計されていると思います。

時系列を自由に進んだり戻ったりできないことは一見するとデメリットですが、誤解の少ないインジケーターやストラテジーをつくりやすいというメリットもあります。

タイムゾーンを指定して、正確な時刻の判定

タイムゾーンと時刻から、対象のローソク足にタテ線を引くコードです。

//@version=5
indicator( "target timestamp", overlay=true )

base_hour     = input.int( 17, "Hour", minval=0, maxval=23 )
base_minute   = input.int( 0, "Minute", minval=0, maxval=59 )
base_timezone = input.string( "America/New_York", "Timezone", options=["America/New_York","Asia/Tokyo","Etc/UTC","America/Los_Angeles","America/Chicago","America/Phoenix","America/Toronto","America/Vancouver","America/Argentina/Buenos_Aires","America/El_Salvador","America/Sao_Paulo","America/Bogota","Europe/Moscow","Europe/Athens","Europe/Berlin","Europe/London","Europe/Madrid","Europe/Paris","Europe/Warsaw","Australia/Sydney","Australia/Brisbane","Australia/ACT","Asia/Almaty","Asia/Ashkhabad","Asia/Taipei","Asia/Singapore","Asia/Shanghai","Asia/Seoul","Asia/Dubai","Asia/Hong_Kong","Asia/Bangkok","Pacific/Auckland","Pacific/Honolulu"] )

get_int_tz( str_timezone ) => str_timezone=="America/New_York" ? -4
     : str_timezone=="Asia/Tokyo" ? 9
     : str_timezone=="Etc/UTC" ? 0
     : str_timezone=="America/Los_Angeles" ? -7
     : str_timezone=="America/Chicago" ? -5
     : str_timezone=="America/Phoenix" ? -7
     : str_timezone=="America/Toronto" ? -4
     : str_timezone=="America/Vancouver" ? -7
     : str_timezone=="America/Argentina/Buenos_Aires" ? -3
     : str_timezone=="America/El_Salvador" ? -6
     : str_timezone=="America/Sao_Paulo" ? -3
     : str_timezone=="America/Bogota" ? -5
     : str_timezone=="Europe/Moscow" ? 3
     : str_timezone=="Europe/Athens" ? 3
     : str_timezone=="Europe/Berlin" ? 2
     : str_timezone=="Europe/London" ? 1
     : str_timezone=="Europe/Madrid" ? 2
     : str_timezone=="Europe/Paris" ? 2
     : str_timezone=="Europe/Warsaw" ? 2
     : str_timezone=="Australia/Sydney" ? 10
     : str_timezone=="Australia/Brisbane" ? 10
     : str_timezone=="Australia/ACT" ? 10
     : str_timezone=="Asia/Almaty" ? 6
     : str_timezone=="Asia/Ashkhabad" ? 5
     : str_timezone=="Asia/Taipei" ? 8
     : str_timezone=="Asia/Singapore" ? 8
     : str_timezone=="Asia/Shanghai" ? 8
     : str_timezone=="Asia/Seoul" ? 9
     : str_timezone=="Asia/Dubai" ? 4
     : str_timezone=="Asia/Hong_Kong" ? 8
     : str_timezone=="Asia/Bangkok" ? 7
     : str_timezone=="Pacific/Auckland" ?  12
     : str_timezone=="Pacific/Honolulu" ? -10 : 0

int_adjust_tz = get_int_tz( syminfo.timezone )
int_base_tz = get_int_tz( base_timezone )

checkGMT( h ,m ) =>
    gap = hour - int_adjust_tz + int_base_tz
    gap_day1 = gap >= 24 ? 1 : gap < 0 ? -1 : 0
    gap_day2 = h * 60 + m >= 24 * 60 ? 1 : 0
    gap_day1 + gap_day2

var int target_timestamp = na
hour_tz = hour( time, base_timezone )
if hour_tz == 0 or ( hour != hour[1] and hour_tz <= base_hour )
    target_timestamp := timestamp( base_timezone, year, month, dayofmonth + checkGMT( base_hour, base_minute ), base_hour, base_minute )

if time[1] < target_timestamp and target_timestamp <= time and timeframe.isintraday
    line.new( bar_index, high, bar_index, low, xloc.bar_index, extend.both )

夏時間の判定

timezoneと夏時間の認識

各国のOpen/Closeや、中値・経済指標等の発表時刻を描画するコードです。夏時間や各取引所の時差を認識し調整します。上図では、それぞれ「灰色:日本」「赤:香港」「青:ロンドン」「オレンジ:米国」を表しています。

//@version=5
indicator( 'timezone and summer time', overlay=true )

////
// 夏時間の判別
//
var s_ny_st = time
var s_uk_st = time
var e_ny_st = time
var e_uk_st = time
if( month[1] == 2 and month == 3 )
    remainder_s = ( 31 - dayofmonth ) % 7
    calc_pointday_s = 31 - remainder_s
    target_date_s_uk = 8 - dayofweek <= remainder_s ? calc_pointday_s + ( 8 - dayofweek ) : calc_pointday_s - ( dayofweek - 1 )
    s_uk_st := timestamp( "GMT", year, 3, target_date_s_uk, 1, 0 )
    target_date_s_ny = dayofweek <= dayofmonth ? dayofmonth - ( dayofweek -1 ) : dayofmonth + ( 8 - dayofweek )
    s_ny_st := timestamp( "GMT-4", year, 3, target_date_s_ny + 7, 2, 0 )
if( month[1] == 9 and month == 10 )
    remiander_e = ( 31 - dayofmonth ) % 7
    calc_pointday_e = 31 - remiander_e  
    target_date_e_uk = 8 - dayofweek <= remiander_e ? calc_pointday_e + ( 8 - dayofweek ) : calc_pointday_e - ( dayofweek - 1 )
    e_uk_st := timestamp( "GMT", year, 10, target_date_e_uk, 1, 0 )
if( month[1] == 10 and month == 11 )
    target_date_e_ny = dayofweek <= dayofmonth ? dayofmonth - ( dayofweek -1 ) : dayofmonth + ( 8 - dayofweek )
    e_ny_st := timestamp( "GMT-4", year, 11, target_date_e_ny, 2, 0 )
toggle_ny_st = ( 3 < month and month < 11 ) or ( month==3 and s_ny_st <= time ) or ( month==11 and time <= e_ny_st )
toggle_uk_st = ( 3 < month and month < 10 ) or ( month==3 and s_uk_st <= time ) or ( month==10 and time <= e_uk_st )

get_int_tz( str_timezone ) => str_timezone=="America/New_York" ? -4
     : str_timezone=="Asia/Tokyo" ? 9
     : str_timezone=="Etc/UTC" ? 0
     : str_timezone=="America/Los_Angeles" ? -7
     : str_timezone=="America/Chicago" ? -5
     : str_timezone=="America/Phoenix" ? -7
     : str_timezone=="America/Toronto" ? -4
     : str_timezone=="America/Vancouver" ? -7
     : str_timezone=="America/Argentina/Buenos_Aires" ? -3
     : str_timezone=="America/El_Salvador" ? -6
     : str_timezone=="America/Sao_Paulo" ? -3
     : str_timezone=="America/Bogota" ? -5
     : str_timezone=="Europe/Moscow" ? 3
     : str_timezone=="Europe/Athens" ? 3
     : str_timezone=="Europe/Berlin" ? 2
     : str_timezone=="Europe/London" ? 1
     : str_timezone=="Europe/Madrid" ? 2
     : str_timezone=="Europe/Paris" ? 2
     : str_timezone=="Europe/Warsaw" ? 2
     : str_timezone=="Australia/Sydney" ? 10
     : str_timezone=="Australia/Brisbane" ? 10
     : str_timezone=="Australia/ACT" ? 10
     : str_timezone=="Asia/Almaty" ? 6
     : str_timezone=="Asia/Ashkhabad" ? 5
     : str_timezone=="Asia/Taipei" ? 8
     : str_timezone=="Asia/Singapore" ? 8
     : str_timezone=="Asia/Shanghai" ? 8
     : str_timezone=="Asia/Seoul" ? 9
     : str_timezone=="Asia/Dubai" ? 4
     : str_timezone=="Asia/Hong_Kong" ? 8
     : str_timezone=="Asia/Bangkok" ? 7
     : str_timezone=="Pacific/Auckland" ?  12
     : str_timezone=="Pacific/Honolulu" ? -10 : 0

int_adjust_tz = get_int_tz( syminfo.timezone )

checkGMT( gtm, h, m ) =>
    gap = hour - int_adjust_tz + gtm
    gap_day1 = gap >= 24 ? 1 : gap < 0 ? -1 : 0
    gap_day2 = h * 60 + m >= 24 * 60 ? 1 : 0
    gap_day1 + gap_day2

var jp1_open  = time
var jp_fix    = time
var jp1_close = time
var jp2_open  = time
var jp2_close = time
var hk1_open  = time
var hk1_close = time
var hk2_open  = time
var hk2_close = time
var uk_open   = time
var uk_fix    = time
var uk_close  = time
var us_econ   = time
var ny_open   = time
var ny_close  = time

arr_lines = array.new_line( 15, na )
arr_linefills = array.new_linefill( 6, na )
set_line_and_linefill( bar_index1, bar_index2, i1, i2, i_linefill, plot_color ) =>
    line_id_1 = line.new( bar_index1, high, bar_index1, low, xloc.bar_time, extend.both, plot_color )
    line_id_2 = line.new( bar_index2, high, bar_index2, low, xloc.bar_time, extend.both, plot_color )
    linefill_id = linefill.new( line_id_1, line_id_2, color.new( plot_color, 90 ) )
    array.set( arr_lines, i1, line_id_1 )
    array.set( arr_lines, i2, line_id_2 )
    array.set( arr_linefills, i_linefill, linefill_id )

if timeframe.isintraday
    jp1_open  := timestamp( "GMT+9", year, month, dayofmonth + checkGMT( 9 ,08 ,00 ), 09, 00 )
    jp_fix    := timestamp( "GMT+9", year, month, dayofmonth + checkGMT( 9 ,09 ,55 ), 09, 55 )
    jp1_close := timestamp( "GMT+9", year, month, dayofmonth + checkGMT( 9 ,11 ,00 ), 11, 00 )
    jp2_open  := timestamp( "GMT+9", year, month, dayofmonth + checkGMT( 9 ,12 ,30 ), 12, 30 )
    jp2_close := timestamp( "GMT+9", year, month, dayofmonth + checkGMT( 9 ,17 ,00 ), 15, 00 )
    hk1_open  := timestamp( "GMT+8", year, month, dayofmonth + checkGMT( 8 ,09 ,30 ), 09, 30 )
    hk1_close := timestamp( "GMT+8", year, month, dayofmonth + checkGMT( 8 ,12 ,00 ), 12, 00 )
    hk2_open  := timestamp( "GMT+8", year, month, dayofmonth + checkGMT( 8 ,13 ,30 ), 13, 30 )
    hk2_close := timestamp( "GMT+8", year, month, dayofmonth + checkGMT( 8 ,16 ,00 ), 16, 00 )
    uk_open   := toggle_uk_st ? timestamp( "GMT+1", year, month, dayofmonth + checkGMT( 1 ,08 ,00 ),  08, 00 ) : timestamp( "GMT",   year, month, dayofmonth + checkGMT( 0  ,08 ,00 ), 08, 00 )
    uk_fix    := toggle_uk_st ? timestamp( "GMT+1", year, month, dayofmonth + checkGMT( 1 ,16 ,00 ),  16, 00 ) : timestamp( "GMT",   year, month, dayofmonth + checkGMT( 0  ,16 ,00 ), 16, 00 )
    uk_close  := toggle_uk_st ? timestamp( "GMT+1", year, month, dayofmonth + checkGMT( 1 ,17 ,00 ),  17, 00 ) : timestamp( "GMT",   year, month, dayofmonth + checkGMT( 0  ,17 ,00 ), 17, 00 )
    ny_open   := toggle_ny_st ? timestamp( "GMT-4", year, month, dayofmonth + checkGMT( -4 ,08 ,00 ), 08, 00 ) : timestamp( "GMT-5", year, month, dayofmonth + checkGMT( -5 ,08 ,00 ), 08, 00 )
    us_econ   := toggle_ny_st ? timestamp( "GMT-4", year, month, dayofmonth + checkGMT( -4 ,08 ,30 ), 08, 30 ) : timestamp( "GMT-5", year, month, dayofmonth + checkGMT( -5 ,08 ,30 ), 08, 30 )
    ny_close  := toggle_ny_st ? timestamp( "GMT-4", year, month, dayofmonth + checkGMT( -4 ,17 ,00 ), 17, 00 ) : timestamp( "GMT-5", year, month, dayofmonth + checkGMT( -5 ,17 ,00 ), 17, 00 )
    for line_target in arr_lines 
        line.delete( line_target )
    for linefill_target in arr_linefills 
        linefill.delete( linefill_target )
    set_line_and_linefill( jp1_open, jp1_close, 0, 1, 0, color.gray )
    set_line_and_linefill( jp2_open, jp2_close, 2, 3, 1, color.gray )
    set_line_and_linefill( hk1_open, hk1_close, 4, 5, 2, color.red )
    set_line_and_linefill( hk2_open, hk2_close, 6, 7, 3, color.red )
    set_line_and_linefill( uk_open,  uk_close,  8, 9, 4, color.blue )
    set_line_and_linefill( ny_open,  ny_close, 10,11, 5, color.orange )
    array.set( arr_lines, 12, line.new( jp_fix  ,high ,jp_fix  ,low ,xloc.bar_time ,extend.both ,color.gray ) )
    array.set( arr_lines, 13, line.new( uk_fix  ,high ,uk_fix  ,low ,xloc.bar_time ,extend.both ,color.blue ) )
    array.set( arr_lines, 14, line.new( us_econ ,high ,us_econ ,low ,xloc.bar_time ,extend.both ,color.orange ) )

var is_weekend = false
is_saturday = dayofweek == dayofweek.saturday
is_end_of_sunday = ( dayofweek == dayofweek.sunday and dayofmonth[1] != dayofmonth ) or ( dayofweek[1] == dayofweek.sunday and dayofweek == dayofweek.monday )
if is_saturday
    is_weekend := true
if is_end_of_sunday
    is_weekend := false
JP = not is_weekend and timeframe.isintraday and ( ( jp1_open <= time and time < jp1_close ) or ( jp2_open <= time and time < jp2_close ) ) ? color.new( color.gray, 80 ) : color.new( color.white, 100 )
HK = not is_weekend and timeframe.isintraday and ( ( hk1_open <= time and time < hk1_close ) or ( hk2_open <= time and time < hk2_close ) ) ? color.new( color.red,  80 ) : color.new( color.white, 100 )
UK = not is_weekend and timeframe.isintraday and uk_open <= time and time < uk_close ? color.new( color.blue,   80 ) : color.new( color.white, 100 )
NY = not is_weekend and timeframe.isintraday and ny_open <= time and time < ny_close ? color.new( color.orange, 80 ) : color.new( color.white, 100 )
bgcolor( JP ,title="日本" )
bgcolor( HK ,title="香港" )
bgcolor( UK ,title="ロンドン" )
bgcolor( NY ,title="ニューヨーク" )

bar_indexに加算して、将来のbar_indexを取得

bar_indexで現在の足のインデックスを取得するのですが、最新の足よりも将来の足でも加算で指定することができます。

//@version=5
indicator( 'add to bar_index', overlay=true )
target_datetime = input.time( 0, '基準とする日時', confirm=true, tooltip='基準とするローソク足を選びます' )

var int target_index = na
if time >= target_datetime and time[1] < target_datetime
    target_index := bar_index

set_line( span ) =>
    target = target_index + span
    line.new( target, close, target, close * .95, xloc.bar_index, extend.both )

if not na( target_index ) and barstate.islast
    set_line( 10 )
    set_line( 20 )
    set_line( 30 )
    set_line( 40 )

昔はこれができず、timestampで頑張って算出するしかありませんでした。週をまたいだり祝日があったり、取引所によってOpen/Closeの時間が異なったりと、N本先を正確に取得するのが結構大変でした。

bar_indexによる過去位置の指定には制限がある

PineスクリプトのSeriseは、リアルタイムに入ると5000データ以上さかのぼれません。バッファ(ヒストリカルデータ)の制限が入ります。

I see 'Pine cannot determine the referencing length of a series. Try using max_bars_back' error — TradingView

Find answers to any questions about how to use TradingView — charts, trades, billing, data, desktop & mobile apps and much more. Learn how to use the platform and get the most out of your experience.

www.tradingview.com

I see 'Pine cannot determine the referencing length of a series. Try using max_bars_back' error — TradingView

bar_indexの減算はtimeに変換して処理されている(らしい)ので、bar_index - 6000等の処理を行うとヒストリカルデータの制限に引っかかってしまいます。

メインチャート以外のデータを取得

TradingViewは、価格データに限らず、あらゆるデータを参照することができます。Pineスクリプトの強力なメリットのひとつです。

security()で別の銘柄や時間軸のデータを取得

security()で、チャート以外の銘柄のデータを取得できる。security("usdjpy" ,"D" ,close)closeを、ema(close ,20)などと指定することもできる。以下のコードは、メインチャートの価格を指定した通貨で為替換算するもの。

currency = input("None" ,title="為替換算" ,options=["None" ,"USD" ,"EUR" ,"GBP" ,"AUD" ,"CAD" ,"CHF"])

get_root(currency) =>
     currency=="USD" ? "usdjpy" :
     currency=="EUR" ? "eurjpy" :
     currency=="GBP" ? "gbpjpy" :
     currency=="AUD" ? "audjpy" :
     currency=="CAD" ? "cadjpy" :
     currency=="CHF" ? "chfjpy" :
     "usdjpy"

sc1(currency ,root) =>
     currency=="None" ? 1 :
     security(root ,"D" ,close)

root = get_root(currency)
value = close * sc1(currency ,root)

※ 銘柄コード「4005」など、複数の取引所で同じコードが使われている場合、「TSE:4005」のように取引所コードで渡さないと取得することができない。組込み変数なら、tickerではなくtickeridを使うこと。

メインチャートより上の時間軸の価格を取得することもできる。

//1時間足を取得
Security( syminfo.tickerid ,"60" ,close )

//4時間足を取得
Security( syminfo.tickerid ,"240" ,close )

//日足を取得
Security( syminfo.tickerid ,"D" ,close )

//週足を取得
Security( syminfo.tickerid ,"W" ,close )

//月足を取得
Security( syminfo.tickerid ,"M" ,close )

日足の正確な四本値

OSE:NK225の金~月曜日にかけてなど、Security()で取得する価格データがズレることがある。正確な日足などの四本値が欲しい場合は、以下のように対応する。

※ 少し前の症状なので、改善しているかもしれません。
//@version=4

sessionStart = input( "Morning" ,options=[ "Night" ,"Morning" ]  )

is_nkx = syminfo.root=="NK225" or syminfo.root=="NK225M"

morning_open = hour[1] == 05 and hour == 08 and minute >= 30
night_open = hour[1] == 15 and hour == 16 and minute >= 30

is_morning_open = sessionStart=="Morning" and morning_open
is_night_open = sessionStart=="Night" and night_open

is_open = is_nkx and ( is_morning_open or is_night_open )

var float dayOpen = na

dayOpen := is_open ? open : dayOpen[1]

財務指標や経済データを取得

四本値以外のデータを元にしたストラテジーをつくることができます。せっせと色んなところからデータを集めてくる必要がなくなります。

//@version=5
indicator("request.financial")
f = request.financial("NASDAQ:MSFT", "ACCOUNTS_PAYABLE", "FY")
plot(f)
引用元: Pineスクリプト™ マニュアル - request.financial()
//@version=5
indicator("US GDP")
e = request.economic("US", "GDP")
plot(e)
引用元: Pineスクリプト™ マニュアル - request.economic()

Nasdaq Data Link(旧Quandl)から外部の金融データを取得

TradingView で Quandl のデータを表示

Nasdaq Data Link (旧Quandl) のデータを取得することもできます。人口やGDPの推移、機関投資家の取引状況等を確認することができます。quande()という専用の関数も用意されています。

以下のコードは、CFTCの建玉明細を表示するもの。

//@vertion=3
force_root = input("", title="Override Product")
is_includeoptions = input(false, type=bool, title="Include Options")

fxroot =
    ticker == "USDCAD" ? "CD" :
    ticker == "USDCAD" ? "CD" :
    ticker == "USDCHF" ? "SF" :
    ticker == "USDCZK" ? "CZ" :
    ticker == "USDHUF" ? "FR" :
    ticker == "USDILS" ? "IS" :
    ticker == "USDJPY" ? "JY" :
    ticker == "USDMXN" ? "MP" :
    ticker == "USDNOK" ? "UN" :
    ticker == "USDPLN" ? "PZ" :
    ticker == "USDRUB" ? "RU" :
    ticker == "USDSEK" ? "SE" :
    ticker == "USDZAR" ? "RA" :
    ticker == "EURUSD" ? "EC" :
    ticker == "AUDUSD" ? "AD" :
    ticker == "GBPUSD" ? "BP" :
    ticker == "NZDUSD" ? "NE" :
    ticker == "BRLUSD" ? "BR" :
    ""

root = force_root == "" ? fxroot == "" ? syminfo.root : fxroot : force_root
code = root + (is_includeoptions ? "_FO" : "_F") + "_L_ALL"

long = security("QUANDL:CFTC/"+code+"|1", "D", close)
short = security("QUANDL:CFTC/"+code+"|2", "D", close)

plot(long, color = red, title="Long" ,style=stepline)
plot(short, color = blue, title="Short" ,style=stepline)
plot(long-short, color = orange, title="Net", style=columns ,transp=50)

Nasdaq Data Link

The source for financial, economic, and alternative datasets, serving investment professionals.

data.nasdaq.com

Nasdaq Data Link

新値足や平均足、カギ足等のデータを取得

新値足のインジケーターをつくったことがありますが、そのときにこれがあれば、もっと簡単につくれていたと思います。

//@version=5
indicator("ticker.linebreak", overlay=true) 
linebreak_tickerid = ticker.linebreak(syminfo.tickerid, 3)
linebreak_close = request.security(linebreak_tickerid, timeframe.period, close)
plot(linebreak_close)
引用元: Pineスクリプト™ マニュアル - ticker.linebreak()

security_lower_tf()で下位足のデータを取得

例えば、日足のUSDJPYで上記のコードを動かすと、各足ごとに1時間足24本分の配列を取得できます。このとき、i=0が最も古いデータになります。

表示しているチャートよりも大きな足種のデータを取りにいくと、エラーが返るので注意が必要です。

//@version=5
indicator("`request.security_lower_tf()` Example", overlay = true)

// If the current chart timeframe is set to 120 minutes, then the `arrayClose` array will contain two 'close' values from the 60 minute timeframe for each bar.
arrClose = request.security_lower_tf(syminfo.tickerid, "60", close)

if bar_index == last_bar_index - 1
    label.new(bar_index, high, str.tostring(arrClose))
引用元: Pineスクリプト™ マニュアル - request.security_lower_tf()

seed()でgithub上のデータにアクセスできるように!

外部データを自由に取得ができないことがPineスクリプトの大きな弱点の一つだったのですが、いつの間にか克服されていました!

//@version=5
indicator("BTC Development Activity")

[devAct, devActSMA] = request.seed("seed_crypto_santiment", "BTC_DEV_ACTIVITY", [close, ta.sma(close, 10)])

plot(devAct, "BTC Development Activity")
plot(devActSMA, "BTC Development Activity SMA10", color = color.yellow)
引用元: Pineスクリプト™ マニュアル - request.seed()

例えば、Pythonで機械学習させて、その結果をTradingViewに取り込むような使い方ができるんじゃないかなと思います。めちゃくちゃ幅が広がります(やりませんが)。

直線を引く

naで間を空けて

TradingView Pineスクリプト チャートに直線を引く①

naが入ると、有効なデータの点と点を直線でつないでくれる。

//@version=3

isRegularFractal(mode) =>
    ret = mode == 1 ? high[4] < high[3] and high[3] < high[2] and high[2] > high[1] and high[1] > high[0] : mode == -1 ? low[4] > low[3] and low[3] > low[2] and low[2] < low[1] and low[1] < low[0] : false

topFractal = isRegularFractal(1) ? high[2] : isRegularFractal(-1) ? low[2] : na

plot(topFractal ,color=red ,offset=-2)

上昇幅を算出して

TradingView Pineスクリプト チャートに直線を引く②

タイムラインと上昇幅を算出して、力技で直線を引く。

//@version=3

shortl   = input(10)
longl    = input(100)
offset_f = input(2)
offset_b = input(20)

// タイムラインを作成しておく
timeline = 0
timeline:= nz(timeline[1]) + 1

// ボトムを探す
a = valuewhen(low==lowest(low ,shortl) ,low ,0)
b = valuewhen(low==lowest(low ,longl)  ,low ,0)
whena = valuewhen(low==lowest(low ,shortl) ,timeline ,0)
whenb = valuewhen(low==lowest(low ,longl)  ,timeline ,0)

m                 = (b-a) / (whenb-whena)
bot_price         = m * (timeline-whena) + a
back_bot_price    = m * (timeline-whena-offset_b) + a
forward_bot_price = m * (timeline-whena+offset_f) + a
bot_price        := b-a==0 ? nz(bot_price[1]) : bot_price
same_bot          = a==a[1] and b==b[1] and a!=0 and b!=0 and whena!=whenb

plot(same_top ? top_price         : na ,style=linebr ,color=red ,linewidth=2 ,offset= 0        ,transp=50 ,title="_top")
plot(same_top ? back_top_price    : na ,style=linebr ,color=red ,linewidth=1 ,offset=-offset_b ,transp=50 ,title="back_top")
plot(same_top ? forward_top_price : na ,style=linebr ,color=red ,linewidth=1 ,offset= offset_f ,transp=70 ,title="forward_top")

line.new()を使って

pineスクリプトのline.new()でタテ線やヨコ線を描画する

使いやすい。

//@version=4

showHL = input( true  ,title="当日クローズまでの ヨコ線 を描画 (30分足以下)")
showVL = input( true  ,title="当日クローズまでの タテ線 の描画 (30分足以下)" )

is_intraday_smaller30 = timeframe.isintraday and timeframe.multiplier <= 30

b4high5 = security( syminfo.tickerid ,"D" ,highest( high ,5 )[1] ,lookahead=barmerge.lookahead_on )
b4low5  = security( syminfo.tickerid ,"D" ,lowest( low ,5 )[1]   ,lookahead=barmerge.lookahead_on )
b4mid5  = ( b4high5 + b4low5 ) / 2

is_nan = b4atr[1]!=b4atr

var start     = time
var end       = time

if is_nan and is_intraday_smaller30
    start := timestamp( year,month,dayofmonth,hour,minute )
    end   := timestamp( year,month, dayofmonth + 1 ,hour,minute )

var line ln_high5 = na
var line ln_mid5 = na
var line ln_low5 = na

var line ln_01 = na
var line ln_02 = na

if showHL
    line.delete( ln_high5 )
    line.delete( ln_mid5 )
    line.delete( ln_low5 )
    ln_high5 := line.new( start ,b4high5 ,end ,b4high5 ,xloc.bar_time )
    ln_mid5  := line.new( start ,b4mid5  ,end ,b4mid5  ,xloc.bar_time )
    ln_low5  := line.new( start ,b4low5  ,end ,b4low5  ,xloc.bar_time )

if showVL
    line.delete( ln_01 )
    line.delete( ln_02 )
    ln_01 := line.new( start ,b4high5 ,end ,b4low5 ,xloc.bar_time )
    ln_02 := line.new( start ,b4high5 ,end ,b4low5 ,xloc.bar_time )

poly.new()を使って

Volume Profile with a few polylines 引用元: Volume Profile with a few polylines - fikira

1つのオブジェクトで複雑な描画ができます。

こういうグラフは、今まではboxやlineをたくさん並べるしかなく500個までという制限がありましたが、1つのオブジェクトで解決できるようになりました。曲線の描画もでき、表現の幅が広がります。

詳細なマーケットプロファイルのインジケーターとか、作れると思います。

Pineスクリプト™ マニュアル - plyline.new()

jp.tradingview.com

Pineスクリプト™ マニュアル - plyline.new()

塗りつぶす

Pineスクリプトはこの塗りつぶしが使いやすく、MQLよりもキレイなインジケーターがつくりやすいです。

fill()

plot同士やhline同士の間を塗りつぶすことができます。plot同士ならグラデーションにすることもできます。

//@version=5
indicator("Fill between plots", overlay = true)
p1 = plot(open)
p2 = plot(close)
fill(p1, p2, color = color.new(color.green, 90))
引用元: Pineスクリプト™ マニュアル - fill()

linefill.new()

line.new()で描画した2つのラインの間を塗りつぶすことができます。夏時間の判定のコードで使っています。

Pineスクリプト™ マニュアル - linefill

jp.tradingview.com

Pineスクリプト™ マニュアル - linefill

box.new()

2点を指定して、boxを描画することができます。

//@version=5
indicator("box.new")
var b = box.new(time, open, time + 60 * 60 * 24, close, xloc=xloc.bar_time, border_style=line.style_dashed)
box.set_lefttop(b, time, 100)
box.set_rightbottom(b, time + 60 * 60 * 24, 500)
box.set_bgcolor(b, color.green)
引用元: Pineスクリプト™ マニュアル - box.new()

情報を格納する

配列(array)

配列は情報の格納に非常によく使います。この記事の中でも、夏時間の判定のコードで情報の格納に使っています。同じ処理でも短いコードで記述できるようになり、管理も容易になります。

以下のコードでは、取得している全データの、実体と窓の「平均」「標準偏差」(いずれも対数の差分)を算出しています。

//@version=5

stdev_multiplier = 2

body = math.log(close) - math.log(open)
body_abs = math.abs(body)
var array_body = array.new_float(0)
array.push(array_body, body_abs)
body_mean = array.avg(array_body)
body_stdev = array.stdev(array_body)

gap = math.log(open) - math.log(close[1])
gap_abs = math.abs(gap)
var array_gap = array.new_float(0)
if gap > 0
    array.push(array_gap, gap_abs)
gap_mean = array.avg(array_gap)
gap_stdev = array.stdev(array_gap)

plot( body_abs, "body", color=color.red )
plot( body_mean + body_stdev * stdev_multiplier ,"body mean + stdev", color=color.red )
plot( gap_abs, "gap" )
plot( gap_mean + gap_stdev * stdev_multiplier ,"gap mena + stdev" )

相関係数一覧表

相関係数一覧表

以下は、配列を活用して相関係数一覧表を作成しています。

//@version=5
indicator( '相関係数一覧表', precision=2, overlay=true )

s1 = input.symbol( '', inline='s1' )
s2 = input.symbol( '', inline='s2' )
s3 = input.symbol( '', inline='s3' )
s4 = input.symbol( '', inline='s4' )
s5 = input.symbol( '', inline='s5' )
s6 = input.symbol( '', inline='s6' )
s7 = input.symbol( '', inline='s7' )
s8 = input.symbol( '', inline='s8' )
s9 = input.symbol( '', inline='s9' )
s10 = input.symbol( '', inline='s10' )
timeframe = input.timeframe( 'D', '時間軸', inline="算出の条件", group="算出の条件"  )
len = input( 1000, inline="算出の条件", group="算出の条件" )
threshold_high = input( .8, "強", inline="強い相関", group="相関表の設定" )
color_high_p = input.color( color.red, "順", inline="強い相関", group="相関表の設定" )
color_high_m = input.color( color.red, "逆", inline="強い相関", group="相関表の設定" )
threshold_mid = input( .6, "中", inline="中程度の相関", group="相関表の設定" )
color_mid_p = input( color.yellow, "順", inline="中程度の相関", group="相関表の設定" )
color_mid_m = input( color.yellow, "逆", inline="中程度の相関", group="相関表の設定" )
color_low = input( color.new( #eeeeee, 0 ), "弱", inline="弱い相関", group="相関表の設定" )
color_same = input( color.black, "同じ銘柄", inline="弱い相関", group="相関表の設定" )
color_base = input( color.white, "背景", inline="色", group="相関表の設定" )
color_text = input( color.black, "テキスト", inline="色", group="相関表の設定" )

num = 10
get_color( x ) => x > .999 ? color_same
     : x >= threshold_high ? color_high_p
     : x >= threshold_mid ? color_mid_p
     : x <= -threshold_high ? color_high_m
     : x <= -threshold_mid ? color_mid_m
     : color_low

close_s1 = s1=='' ? na : request.security( s1, timeframe, close )
close_s2 = s2=='' ? na : request.security( s2, timeframe, close )
close_s3 = s3=='' ? na : request.security( s3, timeframe, close )
close_s4 = s4=='' ? na : request.security( s4, timeframe, close )
close_s5 = s5=='' ? na : request.security( s5, timeframe, close )
close_s6 = s6=='' ? na : request.security( s6, timeframe, close )
close_s7 = s7=='' ? na : request.security( s7, timeframe, close )
close_s8 = s8=='' ? na : request.security( s8, timeframe, close )
close_s9 = s9=='' ? na : request.security( s9, timeframe, close )
close_s10 = s10=='' ? na : request.security( s10, timeframe, close )

var arr_correl_s1 = array.new_float( num, na )
var arr_correl_s2 = array.new_float( num, na )
var arr_correl_s3 = array.new_float( num, na )
var arr_correl_s4 = array.new_float( num, na )
var arr_correl_s5 = array.new_float( num, na )
var arr_correl_s6 = array.new_float( num, na )
var arr_correl_s7 = array.new_float( num, na )
var arr_correl_s8 = array.new_float( num, na )
var arr_correl_s9 = array.new_float( num, na )
var arr_correl_s10 = array.new_float( num, na )

array.set( arr_correl_s1, 0, math.round( ta.correlation( close_s1, close_s1, len ), 2 ) )
array.set( arr_correl_s1, 1, math.round( ta.correlation( close_s1, close_s2, len ), 2 ) )
array.set( arr_correl_s1, 2, math.round( ta.correlation( close_s1, close_s3, len ), 2 ) )
array.set( arr_correl_s1, 3, math.round( ta.correlation( close_s1, close_s4, len ), 2 ) )
array.set( arr_correl_s1, 4, math.round( ta.correlation( close_s1, close_s5, len ), 2 ) )
array.set( arr_correl_s1, 5, math.round( ta.correlation( close_s1, close_s6, len ), 2 ) )
array.set( arr_correl_s1, 6, math.round( ta.correlation( close_s1, close_s7, len ), 2 ) )
array.set( arr_correl_s1, 7, math.round( ta.correlation( close_s1, close_s8, len ), 2 ) )
array.set( arr_correl_s1, 8, math.round( ta.correlation( close_s1, close_s9, len ), 2 ) )
array.set( arr_correl_s1, 9, math.round( ta.correlation( close_s1, close_s10, len ), 2 ) )

array.set( arr_correl_s2, 0, math.round( ta.correlation( close_s2, close_s1, len ), 2 ) )
array.set( arr_correl_s2, 1, math.round( ta.correlation( close_s2, close_s2, len ), 2 ) )
array.set( arr_correl_s2, 2, math.round( ta.correlation( close_s2, close_s3, len ), 2 ) )
array.set( arr_correl_s2, 3, math.round( ta.correlation( close_s2, close_s4, len ), 2 ) )
array.set( arr_correl_s2, 4, math.round( ta.correlation( close_s2, close_s5, len ), 2 ) )
array.set( arr_correl_s2, 5, math.round( ta.correlation( close_s2, close_s6, len ), 2 ) )
array.set( arr_correl_s2, 6, math.round( ta.correlation( close_s2, close_s7, len ), 2 ) )
array.set( arr_correl_s2, 7, math.round( ta.correlation( close_s2, close_s8, len ), 2 ) )
array.set( arr_correl_s2, 8, math.round( ta.correlation( close_s2, close_s9, len ), 2 ) )
array.set( arr_correl_s2, 9, math.round( ta.correlation( close_s2, close_s10, len ), 2 ) )

array.set( arr_correl_s3, 0, math.round( ta.correlation( close_s3, close_s1, len ), 2 ) )
array.set( arr_correl_s3, 1, math.round( ta.correlation( close_s3, close_s2, len ), 2 ) )
array.set( arr_correl_s3, 2, math.round( ta.correlation( close_s3, close_s3, len ), 2 ) )
array.set( arr_correl_s3, 3, math.round( ta.correlation( close_s3, close_s4, len ), 2 ) )
array.set( arr_correl_s3, 4, math.round( ta.correlation( close_s3, close_s5, len ), 2 ) )
array.set( arr_correl_s3, 5, math.round( ta.correlation( close_s3, close_s6, len ), 2 ) )
array.set( arr_correl_s3, 6, math.round( ta.correlation( close_s3, close_s7, len ), 2 ) )
array.set( arr_correl_s3, 7, math.round( ta.correlation( close_s3, close_s8, len ), 2 ) )
array.set( arr_correl_s3, 8, math.round( ta.correlation( close_s3, close_s9, len ), 2 ) )
array.set( arr_correl_s3, 9, math.round( ta.correlation( close_s3, close_s10, len ), 2 ) )

array.set( arr_correl_s4, 0, math.round( ta.correlation( close_s4, close_s1, len ), 2 ) )
array.set( arr_correl_s4, 1, math.round( ta.correlation( close_s4, close_s2, len ), 2 ) )
array.set( arr_correl_s4, 2, math.round( ta.correlation( close_s4, close_s3, len ), 2 ) )
array.set( arr_correl_s4, 3, math.round( ta.correlation( close_s4, close_s4, len ), 2 ) )
array.set( arr_correl_s4, 4, math.round( ta.correlation( close_s4, close_s5, len ), 2 ) )
array.set( arr_correl_s4, 5, math.round( ta.correlation( close_s4, close_s6, len ), 2 ) )
array.set( arr_correl_s4, 6, math.round( ta.correlation( close_s4, close_s7, len ), 2 ) )
array.set( arr_correl_s4, 7, math.round( ta.correlation( close_s4, close_s8, len ), 2 ) )
array.set( arr_correl_s4, 8, math.round( ta.correlation( close_s4, close_s9, len ), 2 ) )
array.set( arr_correl_s4, 9, math.round( ta.correlation( close_s4, close_s10, len ), 2 ) )

array.set( arr_correl_s5, 0, math.round( ta.correlation( close_s5, close_s1, len ), 2 ) )
array.set( arr_correl_s5, 1, math.round( ta.correlation( close_s5, close_s2, len ), 2 ) )
array.set( arr_correl_s5, 2, math.round( ta.correlation( close_s5, close_s3, len ), 2 ) )
array.set( arr_correl_s5, 3, math.round( ta.correlation( close_s5, close_s4, len ), 2 ) )
array.set( arr_correl_s5, 4, math.round( ta.correlation( close_s5, close_s5, len ), 2 ) )
array.set( arr_correl_s5, 5, math.round( ta.correlation( close_s5, close_s6, len ), 2 ) )
array.set( arr_correl_s5, 6, math.round( ta.correlation( close_s5, close_s7, len ), 2 ) )
array.set( arr_correl_s5, 7, math.round( ta.correlation( close_s5, close_s8, len ), 2 ) )
array.set( arr_correl_s5, 8, math.round( ta.correlation( close_s5, close_s9, len ), 2 ) )
array.set( arr_correl_s5, 9, math.round( ta.correlation( close_s5, close_s10, len ), 2 ) )

array.set( arr_correl_s6, 0, math.round( ta.correlation( close_s6, close_s1, len ), 2 ) )
array.set( arr_correl_s6, 1, math.round( ta.correlation( close_s6, close_s2, len ), 2 ) )
array.set( arr_correl_s6, 2, math.round( ta.correlation( close_s6, close_s3, len ), 2 ) )
array.set( arr_correl_s6, 3, math.round( ta.correlation( close_s6, close_s4, len ), 2 ) )
array.set( arr_correl_s6, 4, math.round( ta.correlation( close_s6, close_s5, len ), 2 ) )
array.set( arr_correl_s6, 5, math.round( ta.correlation( close_s6, close_s6, len ), 2 ) )
array.set( arr_correl_s6, 6, math.round( ta.correlation( close_s6, close_s7, len ), 2 ) )
array.set( arr_correl_s6, 7, math.round( ta.correlation( close_s6, close_s8, len ), 2 ) )
array.set( arr_correl_s6, 8, math.round( ta.correlation( close_s6, close_s9, len ), 2 ) )
array.set( arr_correl_s6, 9, math.round( ta.correlation( close_s6, close_s10, len ), 2 ) )

array.set( arr_correl_s7, 0, math.round( ta.correlation( close_s7, close_s1, len ), 2 ) )
array.set( arr_correl_s7, 1, math.round( ta.correlation( close_s7, close_s2, len ), 2 ) )
array.set( arr_correl_s7, 2, math.round( ta.correlation( close_s7, close_s3, len ), 2 ) )
array.set( arr_correl_s7, 3, math.round( ta.correlation( close_s7, close_s4, len ), 2 ) )
array.set( arr_correl_s7, 4, math.round( ta.correlation( close_s7, close_s5, len ), 2 ) )
array.set( arr_correl_s7, 5, math.round( ta.correlation( close_s7, close_s6, len ), 2 ) )
array.set( arr_correl_s7, 6, math.round( ta.correlation( close_s7, close_s7, len ), 2 ) )
array.set( arr_correl_s7, 7, math.round( ta.correlation( close_s7, close_s8, len ), 2 ) )
array.set( arr_correl_s7, 8, math.round( ta.correlation( close_s7, close_s9, len ), 2 ) )
array.set( arr_correl_s7, 9, math.round( ta.correlation( close_s7, close_s10, len ), 2 ) )

array.set( arr_correl_s8, 0, math.round( ta.correlation( close_s8, close_s1, len ), 2 ) )
array.set( arr_correl_s8, 1, math.round( ta.correlation( close_s8, close_s2, len ), 2 ) )
array.set( arr_correl_s8, 2, math.round( ta.correlation( close_s8, close_s3, len ), 2 ) )
array.set( arr_correl_s8, 3, math.round( ta.correlation( close_s8, close_s4, len ), 2 ) )
array.set( arr_correl_s8, 4, math.round( ta.correlation( close_s8, close_s5, len ), 2 ) )
array.set( arr_correl_s8, 5, math.round( ta.correlation( close_s8, close_s6, len ), 2 ) )
array.set( arr_correl_s8, 6, math.round( ta.correlation( close_s8, close_s7, len ), 2 ) )
array.set( arr_correl_s8, 7, math.round( ta.correlation( close_s8, close_s8, len ), 2 ) )
array.set( arr_correl_s8, 8, math.round( ta.correlation( close_s8, close_s9, len ), 2 ) )
array.set( arr_correl_s8, 9, math.round( ta.correlation( close_s8, close_s10, len ), 2 ) )

array.set( arr_correl_s9, 0, math.round( ta.correlation( close_s9, close_s1, len ), 2 ) )
array.set( arr_correl_s9, 1, math.round( ta.correlation( close_s9, close_s2, len ), 2 ) )
array.set( arr_correl_s9, 2, math.round( ta.correlation( close_s9, close_s3, len ), 2 ) )
array.set( arr_correl_s9, 3, math.round( ta.correlation( close_s9, close_s4, len ), 2 ) )
array.set( arr_correl_s9, 4, math.round( ta.correlation( close_s9, close_s5, len ), 2 ) )
array.set( arr_correl_s9, 5, math.round( ta.correlation( close_s9, close_s6, len ), 2 ) )
array.set( arr_correl_s9, 6, math.round( ta.correlation( close_s9, close_s7, len ), 2 ) )
array.set( arr_correl_s9, 7, math.round( ta.correlation( close_s9, close_s8, len ), 2 ) )
array.set( arr_correl_s9, 8, math.round( ta.correlation( close_s9, close_s9, len ), 2 ) )
array.set( arr_correl_s9, 9, math.round( ta.correlation( close_s9, close_s10, len ), 2 ) )

array.set( arr_correl_s10, 0, math.round( ta.correlation( close_s10, close_s1, len ), 2 ) )
array.set( arr_correl_s10, 1, math.round( ta.correlation( close_s10, close_s2, len ), 2 ) )
array.set( arr_correl_s10, 2, math.round( ta.correlation( close_s10, close_s3, len ), 2 ) )
array.set( arr_correl_s10, 3, math.round( ta.correlation( close_s10, close_s4, len ), 2 ) )
array.set( arr_correl_s10, 4, math.round( ta.correlation( close_s10, close_s5, len ), 2 ) )
array.set( arr_correl_s10, 5, math.round( ta.correlation( close_s10, close_s6, len ), 2 ) )
array.set( arr_correl_s10, 6, math.round( ta.correlation( close_s10, close_s7, len ), 2 ) )
array.set( arr_correl_s10, 7, math.round( ta.correlation( close_s10, close_s8, len ), 2 ) )
array.set( arr_correl_s10, 8, math.round( ta.correlation( close_s10, close_s9, len ), 2 ) )
array.set( arr_correl_s10, 9, math.round( ta.correlation( close_s10, close_s10, len ), 2 ) )

if barstate.islast
    var table_correl = table.new( position.bottom_left, num+2, num+1 )
    table.cell( table_correl, 0, 0, "", bgcolor=color_base, text_color=color_text )
    table.cell( table_correl, 1, 0, "Symbol", bgcolor=color_base, text_color=color_text )

    for i=1 to num
        symbol_i = i==1 ? s1 : i==2 ? s2 : i==3 ? s3 : i==4 ? s4 : i==5 ? s5 : i==6 ? s6 : i==7 ? s7 : i==8 ? s8 : i==9 ? s9 : s10
        if symbol_i != ''
            table.cell( table_correl, i+1, 0, str.tostring( i ), bgcolor=color_base, text_color=color_text )

    for i=1 to num
        symbol_i = i==1 ? s1 : i==2 ? s2 : i==3 ? s3 : i==4 ? s4 : i==5 ? s5 : i==6 ? s6 : i==7 ? s7 : i==8 ? s8 : i==9 ? s9 : s10
        if symbol_i != ''
            correl_1_i = array.get( arr_correl_s1, i-1 )
            correl_2_i = array.get( arr_correl_s2, i-1 )
            correl_3_i = array.get( arr_correl_s3, i-1 )
            correl_4_i = array.get( arr_correl_s4, i-1 )
            correl_5_i = array.get( arr_correl_s5, i-1 )
            correl_6_i = array.get( arr_correl_s6, i-1 )
            correl_7_i = array.get( arr_correl_s7, i-1 )
            correl_8_i = array.get( arr_correl_s8, i-1 )
            correl_9_i = array.get( arr_correl_s9, i-1 )
            correl_10_i = array.get( arr_correl_s10, i-1 )
            table.cell( table_correl, 0, i, str.tostring( i ), bgcolor=color_base, text_color=color_text )
            table.cell( table_correl, 1, i, symbol_i, bgcolor=color_base, text_color=color_text )
            if s1 != ''
                table.cell( table_correl, 2, i, str.tostring( correl_1_i ), bgcolor=get_color( correl_1_i ), text_color=color_text )
            if s2 != ''
                table.cell( table_correl, 3, i, str.tostring( correl_2_i ), bgcolor=get_color( correl_2_i ), text_color=color_text )
            if s3 != ''
                table.cell( table_correl, 4, i, str.tostring( correl_3_i ), bgcolor=get_color( correl_3_i ), text_color=color_text )
            if s4 != ''
                table.cell( table_correl, 5, i, str.tostring( correl_4_i ), bgcolor=get_color( correl_4_i ), text_color=color_text )
            if s5 != ''
                table.cell( table_correl, 6, i, str.tostring( correl_5_i ), bgcolor=get_color( correl_5_i ), text_color=color_text )
            if s6 != ''
                table.cell( table_correl, 7, i, str.tostring( correl_6_i ), bgcolor=get_color( correl_6_i ), text_color=color_text )
            if s7 != ''
                table.cell( table_correl, 8, i, str.tostring( correl_7_i ), bgcolor=get_color( correl_7_i ), text_color=color_text )
            if s8 != ''
                table.cell( table_correl, 9, i, str.tostring( correl_8_i ), bgcolor=get_color( correl_8_i ), text_color=color_text )
            if s9 != ''
                table.cell( table_correl, 10, i, str.tostring( correl_9_i ), bgcolor=get_color( correl_9_i ), text_color=color_text )
            if s10 != ''
                table.cell( table_correl, 11, i, str.tostring( correl_10_i ), bgcolor=get_color( correl_10_i ), text_color=color_text )

matrix

配列は1次元のデータですが、これを2次元にしたものがmatrixです。

Excelでいうと、配列が「1行 × N列」のデータだったのに対して、matrixは「N行 × N列」のデータです。

私自身はあまり活用したことがないのですが、matrixはデータを格納してまとめて計算するのが得意です。

Pineスクリプト™ マニュアル - matrix.new<type>()

jp.tradingview.com

Pineスクリプト™ マニュアル - matrix.new<type>()

map

mapは情報を取り出しやすく格納するのが得意です。JavaScriptなら「連想配列」、Pythonなら「Dictionary」にあたります。

Pineスクリプト™ マニュアル - map.new<type,type>()

jp.tradingview.com

Pineスクリプト™ マニュアル - map.new<type,type>()

情報を表示する

plotshape()を使って

plotshape()でテキストを表示

version3まではこれしかできなかった。textの内容をtostring()で動的に変えるようなことはできない。

//@version=4
data = close >= open
plotshape( data ,text="UP" ,textcolor=color.black ,style=shape.labeldown )

label.new()を使って

bar_indexで位置を指定したり、

ea9d6a26ac7d84d0a7ea64a0336c777b
//@version=4
label.new( bar_index ,high ,"x="+tostring(bar_index)+"\ny="+tostring(high) ,style=label.style_none )

timeで位置を指定することができます。

37a6f45584b7a6d0c08a205106cbb6f0
//@version=4
dt = time - time[1]
var label xy = na
label.delete( xy )
xy := label.new( time+3 * dt ,hlc3 ,"x="+tostring(bar_index)+"\ny="+tostring(high) ,xloc.bar_time ,style=label.style_none )

table.new()を使って

plotshapeやlabelはローソク足に対して情報を表示しますが、tableはチャートウィンドウに情報を配置することができます。

この記事の中の相関係数一覧表でも、tableで情報を表示しています。

その他

複数のシグナルを表示

TradingView Pineスクリプト 複数のシグナルを表示する
//@version=3

a = ema(close ,5)
b = ema(close ,25)
c = ema(close ,50)

sig1 = cross(a ,b)
sig2 = cross(a ,c)
sig3 = cross(b ,c)

p1 = plot(4 ,color=black ,editable=false ,trackprice=false)
p2 = plot(3 ,color=black ,editable=false ,trackprice=false)
p3 = plot(2 ,color=black ,editable=false ,trackprice=false)
p4 = plot(1 ,color=black ,editable=false ,trackprice=false)

fill(p1 ,p2 ,color = sig1 ? red : gray ,title="sig1" ,transp=50)
fill(p2 ,p3 ,color = sig2 ? red : gray ,title="sig2" ,transp=50)
fill(p3 ,p4 ,color = sig3 ? red : gray ,title="sig3" ,transp=50)

直近のデータだけ描画

他にも、plot plotbar plotchar fillなどでもshow_lastを使うことができる。

TradingView Pineスクリプト 直近のデータだけ描画する
plotshape(close, show_last=7)

前々回の安値・高値更新を元にしたトレイリングストップ

TradingView Pineスクリプト トレイリングストップ
//@version=3
vw_low  = valuewhen(low  > low[1]  ,low[1]  ,1)
vw_high = valuewhen(high < high[1] ,high[1] ,1)
low_active  = close > vw_low
high_active = close < vw_high
p1 = plot(low_active  ? vw_low  : na ,linewidth=1 ,color=purple ,style=linebr ,title="前々回の安値更新")
p2 = plot(high_active ? vw_high : na ,linewidth=1 ,color=purple ,style=linebr ,title="前々回の高値更新")

数秘を算出

「Astrology(占星)が有効なら、Numerology(数秘)も有効なんじゃないか」と、ちょっと気になって作成してみたコード。実用性はあまりなさそう。サクッと試せるのはTradingViewの良いところ。

calc_n(target) =>
    n4  = target >= 2000 ? 2 : target >= 1000 ? 1 : 0
    n3_ = target - n4*1000
    n3  = n3_ >= 900 ? 9 : n3_ >= 800 ? 8 : n3_ >= 700 ? 7 : n3_ >= 600 ? 6 : n3_ >= 500 ? 5 : n3_ >= 400 ? 4 : n3_ >= 300 ? 3 : n3_ >= 200 ? 2 : n3_ >= 100 ? 1 : 0
    n2_ = n3_ - n3*100
    n2  = n2_ >= 90 ? 9 : n2_ >= 80 ? 8 : n2_ >= 70 ? 7 : n2_ >= 60 ? 6 : n2_ >= 50 ? 5 : n2_ >= 40 ? 4 : n2_ >= 30 ?