どんな記事
前回、相関係数のプログラムを公開してみましたが、今回は、JavaScriptやgoogle apps scriptをつかって基本的なテクニカル分析を計算させてみます。JavaScriptとgoogle apps scriptの記述は一緒です(ほぼ)。
基本のプログラム
まずはライブラリ化している基本的な関数を。
小数点の桁数を指定して四捨五入する
JavaScriptで小数の計算をさせると、ものすごーく小さいですが誤差がでます。計算上は大きな問題ではないのですが、そのまま出力す ると小数の桁数が大変なことになるので、何気に重宝する関数です。
function roundN(v ,n){
var a=1 ,i;
for(i=0; i<n; i++){
a += "0";
}
return Math.round(v *a) /a;
}
TR(True Range)
ワイルダーさん考案のテクニカル分析でよく使います。
function TR(high,low,last){
var m = Math;
return m.max(m.abs(high -low) ,m.abs(high -last) ,m.abs(low -last));
}
EMA(指数平滑移動平均)
function EMA(N,EMAy,P){
return (EMAy *(N -1) +P *2) /(N +1);
}
配列の構造
テクニカル分析を計算するには、元となるデータ が必要です。それが各コードのはじめの部分にあるar = {sym:[[Date ,Open ,High ,Low ,Close]]}
です。これは単に配列の構造を表していて、その構造にもとづいた配列のデータをあらかじめ作っておかないと動きません。
以下で解説します。
var list = ["Date" ,"Open" ,"High" ,"Low" ,"Close" ,"TR" ,"ATR"];
var ar = {
Nikkei225 : [
[2017/01/11 ,19358.64 ,19402.17 ,19325.46 ,19364.67]
,[2017/01/12 ,19300.19 ,19300.19 ,19069.02 ,19134.7]
]
,USDJPY : [
[2017/01/11 ,114.723 ,115.444 ,114.183 ,114.551]
,[2017/01/12 ,115.407 ,115.416 ,113.771 ,114.69]
]
};
var ar = {
Nikkei225 : [
[2017/01/11 ,19358.64 ,19402.17 ,19325.46 ,19364.67]
,[2017/01/12 ,19300.19 ,19300.19 ,19069.02 ,19134.7 ,"計算されたTR" ,"計算されたATR"]
]
,USDJPY : [
[2017/01/11 ,114.723 ,115.444 ,114.183 ,114.551]
,[2017/01/12 ,115.407 ,115.416 ,113.771 ,114.69 ,"計算されたTR" ,"計算されたATR"]]
]
};
このような構造をもとにループ処理で計算をまわしています。JavaScriptのループ処理については詳しく解説しているサイトがたくさんありますので、調べてみてください。
ATR(Average True Range)
平均的な日々の最大変動幅をもとめます。リスク管理に大変有用です。
移動平均はEMAをしようします、EMAの計算には前日のEMAが必要なため、最初の平均値だけ単純平均としています。使用しますが
var
ar = {sym:[[Date ,Open ,High ,Low ,Close]]}
,list = ["Date" ,"Open" ,"High" ,"Low" ,"Close" ,"TR" ,"ATR"]
,n = 20
,r = 2
;
function TR(){
var target = ar[sym][day];
target[list.indexOf("TR")] = roundN(
TR(
target[list.indexOf("High")]
,target[list.indexOf("Low")]
,target[list.indexOf("Close")]
)
);
}
function ATR_(){
var sum = 0;
for(var i=0; i<n; i++){
sum += ar[sym][day-i][list.indexOf("TR")];
}
ar[sym][day][list.indexOf("ATR")] = roundN(sum /n ,r);
}
function ATR(){
ar[sym][day][list.indexOf("ATR")] = roundN(
EMA(
n
,ar[sym][day-1][list.indexOf("ATR")]
,ar[sym][day][list.indexOf("TR")]
)
,r
);
}
HL(ハイローバンド、ドンチャンチャネル)
一定期間の高値と安値。
var
ar = {sym:[[Date ,Open ,High ,Low ,Close]]}
,list = ["Date" ,"Open" ,"High" ,"Low" ,"Close" ,"High20" ,"Low20"]
,n = 20
;
function HL(){
var arHigh = [] ,arLow = [];
for(var i=0; i<n; i++){
arHigh.push(ar[sym][day-i][list.indexOf("High")])
arLow .push(ar[sym][day-i][list.indexOf("Low")])
}
ar[sym][day][list.indexOf("High20")] = Math.max.apply(null ,arHigh);
ar[sym][day][list.indexOf("Low20")] = Math.min.apply(null ,arLow);
}
EMA(指数平滑移動平均)
ライブラリのEMA関数だけだと不十分なので念のため。
var
ar = {sym:[[Date ,Open ,High ,Low ,Close]]}
,list = ["Date" ,"Open" ,"High" ,"Low" ,"Close" ,"EMA20"]
,n = 20
,r = 2
;
function SMA(){
var sum = 0;
for(var i=0; i<n; i++){
sum += ar[sym][day-i][list.indexOf("Close")];
}
ar[sym][day][list.indexOf("EMA20")] = roundN(sum /n ,r);
}
function EMA_(){
ar[sym][day][list.indexOf("EMA20")] = roundN(
EMA(
n
,ar[sym][day-1][list.indexOf("EMA")]
,ar[sym][day][list.indexOf("Close")]
)
,r
);
}
MACD
移動平均線の進化系。トレンドフォローのシグナルの中で、今のところ一番使用頻度が高いです。
var
ar = {sym:[[Date ,Open ,High ,Low ,Close ,EMA6 ,EMA19]]}
,list = ["Date" ,"Open" ,"High" ,"Low" ,"Close" ,"EMA6" ,"EMA19" ,"MACD6_19" ,"MACD6_19_EMA9" ,"MACD6_19_2"]
,r = 2
;
function MACD6_19(){
var target = ar[sym][day];
target[list.indexOf("MACD6_19")] = roundN(
target[list.indexOf("EMA6")] -target[list.indexOf("EMA19")]
,r
);
}
function MACD6_19_EMA9_(){
var n = 9 ,sum = 0;
for(var i=0; i<n; i++){
sum += ar[sym][day-i][list.indexOf("MACD6_19")];
}
target[list.indexOf("MACD6_19_EMA9")] = roundN(sum /n ,r);
}
function MACD6_19_EMA9(){
target[list.indexOf("MACD6_19_EMA9")] = roundN(
EMA(
9
,ar[sym][day-1][list.indexOf("MACD6_19_EMA9")]
,ar[sym][day][list.indexOf("MACD6_19")]
)
,r
);
}
function MACD6_19_2(){
var target = ar[sym][day];
target[list.indexOf("MACD6_19_2")] = roundN(
target[list.indexOf("MACD6_19")] -target[list.indexOf("MACD6_19_EMA9")]
,r
);
}
BB(ボリンジャーバンド)
移動平均線のさらなる進化系。これからどんどんバックテストしてみたいテクニカル分析です。
var
ar = {sym:[[Date ,Open ,High ,Low ,Close]]}
,list = ["Date" ,"Open" ,"High" ,"Low" ,"Close" ,"SMA" ,"sigma" ,"plus1_sgm" ,"plus2_sgm" ,"minus1_sgm" ,"minus2_sgm"]
,n = 20
,r = 2
;
function SMA(){
var sum = 0;
for(var i=0; i<n; i++){
sum += ar[sym][day-i][list.indexOf("Close")];
}
ar[sym][day][list.indexOf("SMA")] = roundN(sum /n ,r);
}
function sigma(){
var
target = ar[sym]
,sumx = 0
,xm
,sumxxm = 0
;
for(var i=0; i<n; i++){
var xxi = target[day-i][list.indexOf("Close")]
sumx += xxi;
}
xm = sumx/n;
for(var i=0; i<n; i++){
var xxi = target[day-i][list.indexOf("Close")]
sumxxm += (xx[i]-xm)^2;
}
ar[sym][day][list.indexOf("sigma")] = m.sqrt((sumxxm /n));
}
function BB(){
var
sma = ar[sym][day][list.indexOf("SMA")]
,sigma = ar[sym][day][list.indexOf("sigma")]
;
ar[sym][day][list.indexOf("plus1_sgm")] = sma +sigma;
ar[sym][day][list.indexOf("plus2_sgm")] = sma +sigma *2;
ar[sym][day][list.indexOf("minus1_sgm")] = sma -sigma;
ar[sym][day][list.indexOf("minus2_sgm")] = sma -sigma *2;
}
ADX
数あるテクニカル分析の中で、トレンドの強さを測ることができるものです。
var
ar = {sym:[[Date ,Open ,High ,Low ,Close]]}
,list = ["Date" ,"Open" ,"High" ,"Low" ,"Close" ,"plus_DM" ,"minus_DM" ,"plus_DI" ,"minus_DI" ,"DX" ,"ADX"]
,n = 14
,r = 2
,r_ = 2
;
function DM(){
var
target = ar[sym][day]
,target_ = ar[sym][day-1]
;
ar[sym][day][list.indexOf("pre_plus_DM")] = roundN(
target[list.indexOf("High")] - target_[list.indexOf("High")]
,r
)
ar[sym][day][list.indexOf("pre_minus_DM")] = roundN(
target_[list.indexOf("Low")] - target[list.indexOf("Low")
,r
)
ar[sym][day][list.indexOf("plus_DM")] = pre_plus_DM <0 ? 0
: pre_plus_DM==pre_minus_DM ? 0
: pre_plus_DM <pre_minus_DM ? 0
: pre_plus_DM
;
ar[sym][day][list.indexOf("minus_DM")] = pre_minus_DM <0 ? 0
: pre_minus_DM==pre_plus_DM ? 0
: pre_minus_DM <pre_plus_DM ? 0
: pre_minus_DM
;
}
function DI_DX(){
var
preDI_TR = 0
,pre_plus_DI = 0
,pre_minus_DI = 0
,plus_DI
,minus_DI
,DX
;
for(var i=0; i<n; i++){
var target = ar[sym][day-i];
preDI_TR += target[list.indexOf("TR")];
pre_plus_DI += target[list.indexOf("plus_DM")];
pre_minus_DI += target[list.indexOf("minus_DM")];
}
ar[sym][day][list.indexOf("plus_DI")] = roundN(
pre_plus_DI /preDI_TR *100
,r_
);
ar[sym][day][list.indexOf("minus_DI")] = roundN(
pre_minus_DI /preDI_TR *100
,r_
);
ar[sym][day][list.indexOf("DX")] = roundN(
Math.abs(plus_DI -minus_DI) /(plus_DI +minus_DI) *100
,r_
);
}
function(){
var preADX = 0;
for(var i=0; i<n; i++){
preADX += ar[sym][day-i][list.indexOf("DX")];
}
ar[sym][day][list.indexOf("ADX")] = roundN(preADX /n ,r_);
}
開発を承っています
- Pineスクリプト(インジケーターやストラテジー)
- Google Apps Script
- Python
- MQL4
などの開発を承っています。とくに投資関連が得意です。過去の事例は「実績ページ(不定期更新)」でご確認ください。ご相談は「お問い合わせ」からお願いします。
- 記事をシェア