カテゴリー
[Sass] sassだけで株価ローソク足チャートを描く方法
※ 当ページには【広告/PR】を含む場合があります。
2020/05/22
D3.js
Chart.js
クライアント側で描画時のJavascriptのレンダリング処理が不要になる
描画用のデータ
// とある会社のある日の日足データ
$stock_data: [
// [日付, 始値, 高値, 低値, 終値]
['2020-05-20', 310, 321, 299, 314]
];
ローソク足
データ1つで実験
div
100%
200px
<div class="hiashi-chart">
<div class="hiashi-1"></div>
</div>
.hiashi-chart {
width: 100%;
height: 200px;
padding: 30px;
border: 2px solid black;
.hiashi-1 {
$rect_width: 20px;
$rect_hieght: 314px - 310px; // ① 終値 - 始値
$rect_color: red; // ② 陽線
$line_width: 1px;
$line_height: 321px - 299px; // ③ 高値 - 終値
$line_top_pos: 314px - 321px; // ④ 終値 - 高値
position: relative;
width: $rect_width;
height: $rect_hieght;
background-color: $rect_color;
&::after {
position: absolute;
left: ($rect_width + $line_width) / 2;
top: $line_top_pos;
content: '';
height: $line_height;
border-left: $line_width solid $rect_color;
}
}
}
①:
ローソクの高さ = (終値 - 始値)の絶対値
②:
陽線か陰線か = (終値 - 始値)での正負符号
③:
ヒゲの高さ = (高値 - 終値)の値
④:
ローソクのtopからみたヒゲの描画開始位置 = (終値 - 高値)の値。
今回は終値が基準(=ローソクのtop位置)だったが、
始値が基準の場合には(始値 - 高値)の値を計算する
@mixin化
@mixin
@mixin
@mixin generic_hiashi(
$hiashi-index,
$rect_width: 20px,
$rect_hieght: 0,
$rect_color: red,
$line_width: 1px,
$line_height: 0,
$line_top_pos: 0
) {
.hiashi-#{$hiashi-index} {
position: relative;
width: $rect_width;
height: $rect_hieght;
background-color: $rect_color;
&::after {
position: absolute;
left: ($rect_width + $line_width) / 2;
top: $line_top_pos;
content: '';
height: $line_height;
border-left: $line_width solid $rect_color;
}
}
}
.hiashi-chart {
width: 100%;
height: 200px;
padding: 30px;
border: 2px solid black;
@include generic_hiashi(1, 20px, 314px - 310px, red, 1px, 321px - 299px, 314px - 321px);
}
データ読み込み後のパラメータ自動計算
@mixin generic_hiashi(
$hiashi-index,
$rect_width: 20px,
$line_width: 1px,
$hiashi_data: ['2000-01-01', 0, 0, 0, 0]
) {
.hiashi-#{$hiashi-index} {
position: relative;
width: $rect_width;
$diff: nth($hiashi_data, 5) - nth($hiashi_data, 2);
height: abs($diff * 1px);
$rect_color: red;
@if $diff < 0 {
$rect_color: blue;
}
background-color: $rect_color;
&::after {
position: absolute;
content: '';
left: ($rect_width - $line_width) / 2;
top: (max(nth($hiashi_data, 2), nth($hiashi_data, 5)) - nth($hiashi_data, 3)) * 1px;
height: (nth($hiashi_data, 3) - nth($hiashi_data, 4)) * 1px;
border-left: $line_width solid $rect_color;
}
}
}
.hiashi-chart {
width: 100%;
height: 300px;
padding: 30px;
border: 2px solid black;
@include generic_hiashi(1, 20px, 1px, ['2020-05-20', 310, 321, 299, 314]);
}
配列からローソク足の生成
x軸の平行移動
string
Epoch時間
+ 2020-01-01 00:00:00(国際標準時) ==> 1577804400
+ 2000-01-01 00:00:00(国際標準時) ==> 946652400
+ 2020-01-01 00:00:00(国際標準時) ==> 1589986800
1時間=3600
1日=86400
// とある会社のある日の日足データ
$stock_data: [
// [日付, Epoch時間(GMT), 始値, 高値, 低値, 終値]
['2020-05-20', 1589900400, 310, 321, 299, 314],
['2020-05-19', 1589814000, 305, 319, 301, 311],
['2020-05-18', 1589727600, 304, 325, 302, 312],
['2020-05-15', 1589468400, 310, 311, 297, 304],
['2020-05-14', 1589382000, 300, 309, 294, 298],
['2020-05-13', 1589295600, 299, 305, 292, 295],
['2020-05-12', 1589209200, 295, 301, 285, 290],
['2020-05-11', 1589122800, 291, 302, 286, 290],
['2020-05-08', 1588863600, 284, 300, 276, 280],
['2020-05-07', 1588777200, 285, 288, 273, 288],
];
@function configure-xaxis($source_array, $base_width: 100%) {
$first: nth(nth($source_array, 1), 2);
$last: nth(nth($source_array, length($source_array)), 2);
@return [$first, $last, $base_width , $base_width * 86400 / ($first - $last)];
}
@function epochtime-to-xpos($epoch_date, $x_pos_unit) {
$first: nth($x_pos_unit, 1);
$last: nth($x_pos_unit, 2);
$x_pos: ($last - $epoch_date) / ($last - $first) * nth($x_pos_unit, 3);
@return $x_pos;
}
configure-xaxis
epochtime-to-xpos
y軸方向の補正
@function configure-yaxis($min_limit: 0, $max_limit: 100, $base_hight: 100%) {
@return [$min_limit, $max_limit, $base_hight, $base_hight / ($max_limit - $min_limit)];
}
@function currentprice-to-ypos($current_price, $y_pos_unit) {
$min: nth($y_pos_unit, 1);
$max: nth($y_pos_unit, 2);
$y_pos: ($max - $current_price) / ($max - $min) * nth($y_pos_unit, 3);
@return $y_pos;
}
ミクスインの修正
@mixin generic_hiashi(
$hiashi-index,
$rect_width: 20px,
$line_width: 1px,
$hiashi_data: ['2000-01-01', 946652400, 0, 0, 0, 0],
$xaxis_config: [100, 0, 100px, 100%], // x軸方向の設定パラメータ
$yaxis_config: [0, 100, 300px, 1px] // y軸方向の設定パラメータ
) {
.hiashi-#{$hiashi-index} {
position: absolute;
left: epochtime-to-xpos(nth($hiashi_data, 2), $xaxis_config);
width: $rect_width;
top: currentprice-to-ypos(max(nth($hiashi_data, 3), nth($hiashi_data, 6)), $yaxis_config);
$diff: nth($hiashi_data, 6) - nth($hiashi_data, 3);
height: abs($diff * nth($yaxis_config, 4));
$rect_color: red;
@if $diff < 0 {
$rect_color: blue;
}
background-color: $rect_color;
&::after {
position: absolute;
content: '';
left: ($rect_width - $line_width) / 2;
top: (max(nth($hiashi_data, 3), nth($hiashi_data, 6)) - nth($hiashi_data, 4)) * nth($yaxis_config, 4);
height: (nth($hiashi_data, 4) - nth($hiashi_data, 5)) * nth($yaxis_config, 4);
border-left: $line_width solid $rect_color;
}
&::before {
position: absolute;
font-size: 10px;
content: nth($hiashi_data, 1);
left: 0;
top: 10px;
}
}
}
.hiashi-chart {
position: relative;
$chart_width: 600px;
$chart_height: 200px;
width: $chart_width;
height: $chart_height;
padding: 10px 40px;
border: 2px solid black;
$xaxis_configuration: configure-xaxis($stock_data, $chart_width);
$yaxis_configuration: configure-yaxis(270, 330, $chart_height);
$i: 1;
@each $item in $stock_data {
@include generic_hiashi($i, 20px, 1px, $item, $xaxis_configuration, $yaxis_configuration);
$i: $i + 1;
}
}
<div class="hiashi-chart">
<div class="hiashi-1"></div>
<div class="hiashi-2"></div>
<div class="hiashi-3"></div>
<div class="hiashi-4"></div>
<div class="hiashi-5"></div>
<div class="hiashi-6"></div>
<div class="hiashi-7"></div>
<div class="hiashi-8"></div>
<div class="hiashi-9"></div>
<div class="hiashi-10"></div>
</div>
まとめ
div:nth-child()
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー