|
|
var CNDL_WIDTH = 3; //ローソクの幅
var CNDL_INT = 2; //ローソクの間隔
var CNDL = CNDL_WIDTH + CNDL_INT; //ローソク1本分
var CNDL_HIGE = 1; //ローソク足のひげのオフセット
var XPOS = 3.5; //X座標開始位置(CNDL_INT + CNDL_WIDTH / 2)
var VAL_WIDTH = 70; //チャートの価格表示幅
var COL_CANDLE = "#0000cd"; //ローソク足の色
var COL_AVE5 = "#ff0000"; //5日移動平均線の色
var COL_AVE25 = "#008b8b"; //25日移動平均線の色
var COL_AVE75 = "#ff8c00"; //75日移動平均線の色
var DAYS_TENKAN = 9; //転換線の日数
var DAYS_KIJUN = 26; //基準線の日数
var DAYS_SPAN2 = 52; //先行スパン2の日数
var COL_TENKAN = "#ff0000"; //転換線の色
var COL_KIJUN = "#008b8b"; //基準線の色
var COL_CHIKOU = "#ff8c00"; //遅行線の色
var COL_CLUD1 = "#e6e6fa"; //良い雲の色
var COL_CLUD2 = "#ffe0f0"; //悪い雲の色
var COL_BOLLINGER0 = "#008b8b"; //ボリンジャーバンド25日平均移動線の色
var COL_BOLLINGER1 = "#ff8c00"; //ボリンジャーバンドσ1の色
var COL_BOLLINGER2 = "#4169e1"; //ボリンジャーバンドσ2の色
var COL_BOLLINGER3 = "#ff0000"; //ボリンジャーバンドσ3の色
var COL_ENVELOPE0 = "#008b8b"; //エンベロープ25日平均移動線の色
var COL_ENVELOPE1 = "#ff8c00"; //エンベロープ±2.5%の色
var COL_ENVELOPE2 = "#4169e1"; //エンベロープ±5.0%の色
var COL_ENVELOPE3 = "#ff0000"; //エンベロープ±7.5%の色
var CHT_HIASHI = 1; //日足チャート
var CHT_ICHIMOKU = 2; //一目均衡表
var CHT_ENVELOPE = 3; //エンベロープ
var CHT_BOLLINGER = 4; //ボリンジャーバンド
var gChartHeight; //チャート高さ
var gChartYRate; //1円の高さ
var gMax; //最高値
var gMin; //最安値
var gX; //描画開始X座標
var gCrntChart = 0; //表示中チャート
// 0:非表示
// 1:日足
// 2:一目均衡表
// 3:ボリンジャーバンド
// 4:エンベロープ
//チャート表示
function dspChart() {
//表示中年月インデックス
if (gMonthDataNum.length <= 7) {
gCrntYMIdx = 0;
} else {
gCrntYMIdx = gMonthDataNum.length - 7;
}
//チャート表示サブ
dspChartSub();
}
//スクロール表示
// scrollCnt : スクロール月数
function dspScroll(scrollCnt) {
//表示中年月インデックス
gCrntYMIdx += scrollCnt;
//チャート表示サブ
dspChartSub();
}
//チャート表示サブ
function dspChartSub() {
//初期化
gStartIdx = 0; //チャート表示開始インデックス初期化
gMax = 0; //表示中最大値
gMin = 99999999;//表示中最小値
gCrntChart = 0; //表示中チャート
//チャート表示開始位置を計算
setStartEndIdx();
//チャート縦軸の価格表示
dspChartPrice();
//1円の高さ
gChartHeight = document.getElementById("idchart").height;
gChartYRate = gChartHeight / (gMax - gMin);
//年月表示
dspYearMonth();
//チャート表示
var elm = document.getElementsByName("chartkind");
if (elm[0].checked == true) {
hiashi(); //日足チャート
} else if(elm[1].checked == true) {
envelope(); //エンベロープ
} else if(elm[2].checked == true) {
ichimoku(); //一目均衡表
} else{
bollinger(); //ボリンジャーバンド
}
dspMACD(); //MACD表示
dspStcastics(); //ストキャスティックス表示
dspRSI(); //RSI表示
}
//チャート表示開始、終了インデックスを設定
function setStartEndIdx() {
var i;
if (gCrntYMIdx == 0) {
gStartIdx = 0;
} else {
for (i = 0; i < gCrntYMIdx; i++) {
gStartIdx += gMonthDataNum[i];
}
}
gEndIdx = gStartIdx;
for (i = gCrntYMIdx; i < gMonthDataNum.length && i < gCrntYMIdx + 7; i++) {
gEndIdx += gMonthDataNum[i];
}
gEndIdx--;
}
//チャート縦軸の価格表示
function dspChartPrice() {
var i;
var w;
var a;
//表示年月の最安値、最高値を求める
for (i = gStartIdx; i <= gEndIdx; i++) {
if (gMax < gHi[i]) {
gMax = gHi[i];
}
if (gLo[i] < gMin) {
gMin = gLo[i];
}
}
//最高値、最安値からチャート表示領域の上限値、下限値を計算
calcMaxMin();
//縦軸の価格表示
w = (gMax - gMin) / 10;
a = document.getElementById("vchart1");
a.text = String(gMin + w * 10).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart2");
a.text = String(gMin + w * 9).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart3");
a.text = String(gMin + w * 8).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart4");
a.text = String(gMin + w * 7).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart5");
a.text = String(gMin + w * 6).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart6");
a.text = String(gMin + w * 5).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart7");
a.text = String(gMin + w * 4).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart8");
a.text = String(gMin + w * 3).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart9");
a.text = String(gMin + w * 2).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart10");
a.text = String(gMin + w).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
a = document.getElementById("vchart11");
a.text = String(gMin).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
}
//最高値、最安値からチャート表示領域の上限値、下限値を計算
function calcMaxMin() {
var w;
//チャート表示領域の下限値計算
if (gMin < 10) {
gMin = 0;
} else if (gMin < 100) {
gMin = Math.floor(gMin / 10) * 10;
} else if (gMin < 1000) {
gMin -= (gMin % 10);
} else if (gMin < 10000) {
gMin -= (gMin % 100);
} else if (gMin < 100000) {
gMin -= (gMin % 1000);
} else if (gMin < 1000000) {
gMin -= (gMin % 10000);
} else if (gMin < 10000000) {
gMin -= (gMin % 100000);
} else if (gMin < 100000000) {
gMin -= (gMin % 1000000);
}
//チャート表示領域の上限値計算
w = gMax - gMin;
if (w < 10) {
gMax = gMin + 10;
} else if (w < 100) {
w = Math.floor(w / 10) + 1;
gMax = gMin + w * 10;
} else if (w < 1000) {
w = Math.floor(w / 100) + 1;
gMax = gMin + w * 100;
} else if (w < 10000) {
w = Math.floor(w / 1000) + 1;
gMax = gMin + w * 1000;
} else if (w < 100000) {
w = Math.floor(w / 10000) + 1;
gMax = gMin + w * 10000;
} else if (w < 1000000) {
w = Math.floor(w / 100000) + 1;
gMax = gMin + w * 100000;
} else if (w < 10000000) {
w = Math.floor(w / 1000000) + 1;
gMax = gMin + w * 1000000;
} else if (w < 100000000) {
w = Math.floor(w / 10000000) + 1;
gMax = gMin + w * 10000000;
}
}
//年月表示、幅設定
function dspYearMonth() {
var tblWidth;
//年月表示
dspYearMonthSub("ym1", gCrntYMIdx);
dspYearMonthSub("ym2", gCrntYMIdx+1);
dspYearMonthSub("ym3", gCrntYMIdx+2);
dspYearMonthSub("ym4", gCrntYMIdx+3);
dspYearMonthSub("ym5", gCrntYMIdx+4);
dspYearMonthSub("ym6", gCrntYMIdx+5);
dspYearMonthSub("ym7", gCrntYMIdx+6);
//月の幅設定
tblWidth = setMonthWidth("width1", gCrntYMIdx, gCrntYMIdx+1);
tblWidth += setMonthWidth("width2", gCrntYMIdx+1, gCrntYMIdx+2);
tblWidth += setMonthWidth("width3", gCrntYMIdx+2, gCrntYMIdx+3);
tblWidth += setMonthWidth("width4", gCrntYMIdx+3, gCrntYMIdx+4);
tblWidth += setMonthWidth("width5", gCrntYMIdx+4, gCrntYMIdx+5);
tblWidth += setMonthWidth("width6", gCrntYMIdx+5, gCrntYMIdx+6);
tblWidth += setMonthWidth("width7", gCrntYMIdx+6, gCrntYMIdx+6);
//テーブル幅、キャンバス幅設定
tblWidth += 6;
if ((tblWidth % 2) == 1) {
tblWidth += 1;
} else {
tblWidth -= 2;
}
document.getElementById("idchart").setAttribute("width", tblWidth);
document.getElementById("idmacd").setAttribute("width", tblWidth);
document.getElementById("idstcas").setAttribute("width", tblWidth);
document.getElementById("idrsi").setAttribute("width", tblWidth);
tblWidth += VAL_WIDTH;
document.getElementById("idtable").setAttribute("width", tblWidth);
}
//年月表示サブ
// idname : 年/月のID
// p : 表示対象の年、月のインデックス
function dspYearMonthSub(idname, p) {
var ym = "";
if (gYear[p] != "") {
ym = gYear[p] + "/" + gMonth[p];
}
document.getElementById(idname).text = ym;
}
//月の幅設定サブ
// idname : 年/月のID
// p : 表示対象の月の日数インデックス
// np : 表示対象の次の月の日数インデックス(pが最終月のときはp=np)
function setMonthWidth(idname, p, np) {
var monthWidth = 110;
if (p != gMonthDataNum.length-1) {
if (gMonthDataNum[p] != 0) {
monthWidth = gMonthDataNum[p] * CNDL - 1;
if (gMonthDataNum[np] == 0 && monthWidth < 100) {
monthWidth = 100;
}
if ((gMonthDataNum[p] % 2) == 0) {
monthWidth++;
} else if (gMonthDataNum[p] == 22) {
monthWidth++;
}
}
}
if (idname == "width7") { //表示中最後の月幅は+2
monthWidth += 2;
}
document.getElementById(idname).setAttribute("width", monthWidth);
return monthWidth;
}
//日足チャート
function hiashi(){
if (gCrntChart != CHT_HIASHI) {
gCrntChart = CHT_HIASHI;
getCanvas("idchart"); //キャンバス取得
dspCandle();
drawAverage(5, 1, COL_AVE5); //5日平均線
drawAverage(25, 1, COL_AVE25); //25日平均線
drawAverage(75, 1, COL_AVE75); //75日平均線
}
}
//一目均衡表
function ichimoku(){
var tx; //転換線X座標
var ty; //転換線Y座標
var kx; //基準線X座標
var ky; //基準線Y座標
var sy1; //先行スパン1Y座標
var sy2; //先行スパン2Y座標
if (gCrntChart != CHT_ICHIMOKU) {
gCrntChart = CHT_ICHIMOKU;
tx = new Array(gEd.length);
ty = new Array(gEd.length);
kx = new Array(gEd.length);
ky = new Array(gEd.length);
sy1 = new Array(gEd.length);
sy2 = new Array(gEd.length);
calcTenkaKijun(DAYS_TENKAN, ty);//転換線座標計算
calcTenkaKijun(DAYS_KIJUN, ky); //基準線座標計算
calcSpan1(ty, ky, sy1); //先行スパン1(上限線)計算
calcSpan2(sy2); //先行スパン2(下限線)計算
getCanvas("idchart"); //キャンバス取得
drawCloud(sy1, sy2); //雲表示
dspCandle(); //ローソク足
drawTnknKjn(9, ty, COL_TENKAN); //転換線
drawTnknKjn(26, ky, COL_KIJUN); //基準線
chikou(); //遅行線
}
}
//エンベロープ
function envelope() {
if (gCrntChart != CHT_ENVELOPE) {
gCrntChart = CHT_ENVELOPE;
getCanvas("idchart"); //キャンバス取得
dspCandle();
drawAverage(25, 1, COL_ENVELOPE0); //25日平均線
drawAverage(25, 1.025, COL_ENVELOPE1); // 2.5%
drawAverage(25, 0.975, COL_ENVELOPE1); //-2.5%
drawAverage(25, 1.05, COL_ENVELOPE2); // 5.0%
drawAverage(25, 0.95, COL_ENVELOPE2); //-5.0%
drawAverage(25, 1.075, COL_ENVELOPE3); // 7.5%
drawAverage(25, 0.925, COL_ENVELOPE3); //-7.5%
}
}
//ボリンジャーバンド
function bollinger() {
if (gCrntChart != CHT_BOLLINGER) {
gCrntChart = CHT_BOLLINGER;
getCanvas("idchart"); //キャンバス取得
dspCandle();
drawAverage(25, 1, COL_BOLLINGER0); //25日平均線
drawBollinger(25, 1.0, COL_BOLLINGER1); //σ1
drawBollinger(25, -1.0, COL_BOLLINGER1);//σ1
drawBollinger(25, 2.0, COL_BOLLINGER2); //σ2
drawBollinger(25, -2.0, COL_BOLLINGER2);//σ2
drawBollinger(25, 3.0, COL_BOLLINGER3); //σ3
drawBollinger(25, -3.0, COL_BOLLINGER3);//σ3
}
}
//キャンバス取得
// idname : キャンバスのID
function getCanvas(idname) {
var canvas = document.getElementById(idname);
gCtx = canvas.getContext('2d');
//キャンバスクリア
gCtx.clearRect(0, 0, canvas.width, canvas.height);
//キャンバス位置確認枠描画(座標が正しいか確認)
drawCanvasPos(canvas.height);
}
//キャンバス位置確認枠描画
// height : キャンバスの高さ
function drawCanvasPos(height) {
gCtx.beginPath();
gCtx.strokeStyle = "#ff0000";
gCtx.fillStyle = "#ff0000";
//左上
gCtx.moveTo(0, 0);
gCtx.lineTo(20, 0);
gCtx.moveTo(0, 0);
gCtx.lineTo(0, 20);
//左下
gCtx.moveTo(0, height);
gCtx.lineTo(20, height);
gCtx.moveTo(0, height);
gCtx.lineTo(0, height - 20);
gCtx.stroke();
gCtx.closePath();
}
//ローソク足表示
function dspCandle() {
var i;
var x;
gCtx.strokeStyle = COL_CANDLE;
gCtx.fillStyle = COL_CANDLE;
x = CNDL_INT - 0.5;
for (i = gStartIdx; i <= gEndIdx; i++) {
drawCandle(gSt[i], gHi[i], gLo[i], gEd[i], x);
x += CNDL;
}
}
//ローソク足を1本描画
// st : 始値
// hi : 高値
// lo : 安値
// ed : 終値
function drawCandle(st, hi, lo, ed, x) {
var xhige;
var y1;
var y2;
st = st - gMin;
hi = hi - gMin;
lo = lo - gMin;
ed = ed - gMin;
xhige = x + CNDL_HIGE;
gCtx.beginPath();
if (st == ed) {
if (lo < hi) {
y1 = gChartHeight - lo * gChartYRate + 0.5;
y2 = gChartHeight - hi * gChartYRate + 0.5;
gCtx.moveTo(xhige, y1);
gCtx.lineTo(xhige, y2);
}
y1 = gChartHeight - st * gChartYRate + 0.5;
gCtx.moveTo(x, y1);
gCtx.lineTo(x + CNDL_WIDTH, y1);
} else if (st < ed) {
if (lo < st) {
y1 = gChartHeight - lo * gChartYRate + 0.5;
y2 = gChartHeight - st * gChartYRate + 0.5;
gCtx.moveTo(xhige, y1);
gCtx.lineTo(xhige, y2);
}
y1 = gChartHeight - ed * gChartYRate + 0.5;
y2 = (ed - st) * gChartYRate + 0.5;
gCtx.strokeRect(x, y1, CNDL_WIDTH, y2);
if (ed < hi) {
y1 = gChartHeight - hi * gChartYRate + 0.5;
y2 = gChartHeight - ed * gChartYRate + 0.5;
gCtx.moveTo(xhige, y1);
gCtx.lineTo(xhige, y2);
}
} else {
if (lo < ed) {
y1 = gChartHeight - lo * gChartYRate + 0.5;
y2 = gChartHeight - ed * gChartYRate + 0.5;
gCtx.moveTo(xhige, y1);
gCtx.lineTo(xhige, y2);
}
y1 = gChartHeight - st * gChartYRate + 0.5;
y2 = (st - ed) * gChartYRate + 0.5;
gCtx.fillRect(x, y1, CNDL_WIDTH, y2);
if (st < hi) {
y1 = gChartHeight - hi * gChartYRate + 0.5;
y2 = gChartHeight - st * gChartYRate + 0.5;
gCtx.moveTo(xhige, y1);
gCtx.lineTo(xhige, y2);
}
}
gCtx.stroke();
gCtx.closePath();
}
//平均移動線描画
// nissu : 平均移動線の日数
// jousu : 係数
// color : 表示色
function drawAverage(nissu, keisu, color) {
var i;
var ave;
if ((nissu+1) < gEd.length) {
gCtx.beginPath();
gCtx.strokeStyle = color;
//X座標と計算開始位置を求める
stIdx = getDrawIdx(gStartIdx, nissu);
for (i = stIdx; i <= gEndIdx; i++) {
ave = calcAve(i, nissu);
ave *= keisu;
y = gChartHeight - (ave - gMin) * gChartYRate;
if (i == stIdx) {
gCtx.moveTo(gX, y);
} else {
gCtx.lineTo(gX, y);
}
gX += CNDL;
}
gCtx.stroke();
gCtx.closePath();
}
}
//終値の平均値を計算する
// p : 終値の平均値を計算する開始位置
// nissu : 終値の平均値を計算する日数
function calcAve(p, nissu) {
var i;
var ave = 0;
for (i = nissu - 1; 0 <= i; i--) {
ave += gEd[p - i];
}
ave /= nissu;
return ave;
}
//転換線、基準線の座標計算
// nissu : 転換線または基準線の日数
// y : Y座標計算
function calcTenkaKijun(nissu, y) {
var i;
var j
var low;
var hi;
nissu--;
for (i = nissu - 1; i < gEd.length; i++) {
low = 9999999;
hi = 0;
for (j = i - (nissu - 1); j <= i; j++) {
if (gLo[j] < low) {
low = gLo[j];
}
if (hi < gHi[j]) {
hi = gHi[j];
}
}
y[i] = gChartHeight - (((low + hi) / 2) - gMin) * gChartYRate;
}
}
//先行スパン1計算
// ty : 転換線Y座標
// ky : 基準線Y座標
// sy : 先行スパン1Y座標
function calcSpan1(ty, ky, sy) {
var i;
//転換線と基準線の中間を計算
for (i = DAYS_KIJUN - 1; i < gEd.length; i++) {
sy[i] = (ty[i] + ky[i]) / 2;
}
}
//先行スパン2計算
// sy : 先行スパン2Y座標
function calcSpan2(sy) {
var i;
var j;
var hi;
var lo;
var p;
//過去52日間の高値、安値の平均値を計算
p = DAYS_SPAN2 - 1;
for (i = p; i < gEd.length; i++) {
hi = 0;
lo = 99999999;
for (j = i - p; j <= i; j++) {
if (hi < gHi[j]) {
hi = gHi[j];
}
if (gLo[j] < lo) {
lo = gLo[j];
}
sy[i] = gChartHeight - (((hi + lo) / 2) - gMin) * gChartYRate;
}
}
}
//雲描画
// sy1 : 先行スパン1Y座標
// sy2 : 先行スパン2Y座標
function drawCloud(sy1, sy2) {
var i;
var stIdx;
stIdx = getDrawIdx(gStartIdx, DAYS_SPAN2);
gX -= XPOS;
if (DAYS_SPAN2 < stIdx) {
stIdx -= 26;
if (stIdx < DAYS_SPAN2) {
gX += (CNDL * (DAYS_SPAN2 - stIdx - 1));
stIdx = DAYS_SPAN2 - 1;
}
} else {
gX += (CNDL * 26);
}
gCtx.beginPath();
for (i = stIdx; i < gEd.length - 1; i++) {
if (sy1[i] >= sy2[i]) {
gCtx.strokeStyle = COL_CLUD1;
gCtx.fillStyle = COL_CLUD1;
gCtx.fillRect(gX, sy1[i], CNDL+1, sy2[i] - sy1[i]);
} else {
gCtx.strokeStyle = COL_CLUD2;
gCtx.fillStyle = COL_CLUD2;
gCtx.fillRect(gX, sy2[i], CNDL+1, sy1[i] - sy2[i]);
}
gX += CNDL;
}
gCtx.stroke();
gCtx.closePath();
}
//転換線、基準線描画
// nissu : 日数(9/26)
// y : 転換線または基準線のY座標
// color : 転換線または基準線の色
function drawTnknKjn(nissu, y, color) {
var i;
stIdx = getDrawIdx(gStartIdx, nissu);
gCtx.beginPath();
gCtx.strokeStyle = color;
gCtx.moveTo(gX, y[stIdx]);
for (i = stIdx + 1; i < gEd.length; i++) {
gX += CNDL;
gCtx.lineTo(gX, y[i]);
}
gCtx.stroke();
gCtx.closePath();
}
//遅行線
function chikou() {
var i;
var x = XPOS;
var y;
gCtx.beginPath();
gCtx.strokeStyle = COL_CHIKOU;
for (i = gStartIdx + 25; i < gEd.length; i++) {
y = gChartHeight - (gEd[i] - gMin) * gChartYRate;
if (i == gStartIdx) {
gCtx.moveTo(x, y);
} else {
gCtx.lineTo(x, y);
}
x += CNDL;
}
gCtx.stroke();
gCtx.closePath();
}
//ボリンジャバンド描画
// nissu : アベレージ日数
// jousu : 標準偏差乗数
// color : ボリンジャバンドの色
function drawBollinger(nissu, jousu, color) {
var i;
var j;
var ave;
var sum;
var w;
var variance;
var y;
var stIdx;
if ((nissu+1) < gEd.length) {
gCtx.beginPath();
gCtx.strokeStyle = color;
//X座標と計算開始位置を求める
stIdx = getDrawIdx(gStartIdx, nissu)
//開始インデックスから終了インデックスまでループ
for (i = stIdx; i <= gEndIdx; i++) {
//平均値計算
ave = calcAve(i, nissu);
//分散計算
sum = 0;
for (j = 0; j < nissu; j++) {
w = gEd[i - j] - ave;
sum += (w * w);
}
variance = sum / nissu;
//標準偏差計算
rstdDeviation = Math.sqrt(variance) * jousu;
//X,Y座標
y = gChartHeight - ((ave + rstdDeviation) - gMin) * gChartYRate;
//線描画
if (i == stIdx) {
gCtx.moveTo(gX, y);
} else {
gCtx.lineTo(gX, y);
}
gX += CNDL;
}
gCtx.stroke();
gCtx.closePath();
}
}
//開始インデックスと日数により描画可能な開始インデックスとX座標を求める
// stIdx : 開始インデックス
// nissu : 日数
function getDrawIdx(stIdx, nissu) {
var p;
gX = XPOS;
p = nissu - stIdx;
if (0 < p) {
p--;
gX += CNDL * p;
stIdx += p;
}
return stIdx;
}
|