カテゴリー: tech

  •  go言語で株価を取得する

     go言語で株価を取得する

    はじめに

    株価情報を取得したいことがある。

    go言語ではパッケージを利用することにより株価の取得が非常に簡単にできている。

    利用するライブラリ

    https://github.com/markcheno/go-talib

    サンプルコードや導入手順もこちらに記載されてある。

    go get github.com/markcheno/go-talib
    go get github.com/markcheno/go-quote

    実施するコマンド

    Googleの株価を取得する。

    オリジナルはこちら

    https://finance.yahoo.com/quote/GOOG?p=GOOG&.tsrc=fin-srch

    package main
    
    import (
    	"fmt"
    
    	"github.com/markcheno/go-quote"
    	"github.com/markcheno/go-talib"
    )
    
    func main() {
    	spy, _ := quote.NewQuoteFromYahoo("GOOG", "2019-04-01", "2019-04-04", quote.Daily, true)
    	fmt.Print(spy.CSV())
    	rsi2 := talib.Rsi(spy.Close, 2)
    	fmt.Println(rsi2)
    }

    実行結果

    $ go run main.go
    datetime,open,high,low,close,volume
    2019-04-01 00:00,1184.10,1196.66,1182.00,1194.43,1252500.00
    2019-04-02 00:00,1195.32,1201.35,1185.71,1200.49,827900.00
    2019-04-03 00:00,1207.48,1216.30,1200.50,1205.92,1017800.00
    [0 0 100]

     

     

     

  • go言語でtestingを使ったunittestの方法

    go言語でtestingを使ったunittestの方法

    はじめに

    あらゆるプログラミング言語でunitテストという作業は必要だが、今回はそのgo言語版について説明する。

    今回はgoのデフォルトの “` testing “` を使い、ライブラリのテストを行うものとする。

    ディレクトリ構成

    $ tree
    .
    ├── library
    │   ├── Ave.go # ライブラリ
    │   └── Ave_test.go # ライブラリのテストプログラム
    └── main.go # 呼び出し元

    テスト対象

    library/Ave.go は以下の通り

    package library
    
    func Average(s []int) int {
    	total := 0
    	for _, i := range s {
    		total += i
    	}
    	return int(total / len(s))
    }

    受け取ったスライスを元に、平均を計算し、

    平均値を返す

    テストプログラム

    テストプログラムは

    “` import “testing” “`

    を行い、functionは 

    “` func TestAverage(t *testing.T) “`

    という名前で作成する必要がある。

    package library
    
    import "testing"
    
    func TestAverage(t *testing.T) {
    	v := Average([]int{1, 2, 3, 4, 5})
    	if v != 3 {
    		t.Error("Expected 3, got", v)
    	}
    }

    テストプログラムを実施する

    テスト実施コマンドはこちら

    “` go test ./… “`

    現在のディレクトリで全てのテストプログラムを実施するという意味。

     

    テスト結果(成功時のパターン)

    $ go test ./...
    ?       github.com/GitSumito/go-sample  [no test files] # testがありません
    ok      github.com/GitSumito/go-sample/library  0.009s

    libraryのテストが完了した

    詳細を確認する際は “` -v “` オプションを実施する

    $ go test ./... -v
    ?       github.com/GitSumito/go-sample  [no test files]
    === RUN   TestAverage
    --- PASS: TestAverage (0.00s)
    PASS
    ok      github.com/GitSumito/go-sample/library  0.008s

     

    テスト結果(失敗時のパターン)

    テストコードをあえて失敗するよう修正する

    package library
    
    import "testing"
    
    func TestAverage(t *testing.T) {
    	v := Average([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
    	if v != 3 {
    		t.Error("Expected 3, got", v)
    	}
    }

    再度テストを実行

    $ go test ./... -v
    ?       github.com/GitSumito/go-sample  [no test files]
    === RUN   TestAverage
    --- FAIL: TestAverage (0.00s)
            Ave_test.go:8: Expected 3, got 5
    FAIL
    FAIL    github.com/GitSumito/go-sample/library  0.008s

    テストをskipさせる

    Skipを使うことによりスキップさせることが可能

    package library
    
    import "testing"
    
    var Debug bool = true
    
    func TestAverage(t *testing.T) {
    
    	if Debug {
    		t.Skip("Skip Reason")
    	}
    
    	v := Average([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
    	if v != 3 {
    		t.Error("Expected 3, got", v)
    	}
    }

    結果

    $ go test ./... -v
    ?       github.com/GitSumito/go-sample  [no test files]
    === RUN   TestAverage
    --- SKIP: TestAverage (0.00s)
            Ave_test.go:10: Skip Reason
    PASS
    ok      github.com/GitSumito/go-sample/library  0.009s

     参考情報

    本記事は、udemyの講座で得た情報をメモとしてまとめました。非常に濃厚な講義ですので、以下の講座を強くお勧めします。

    https://www.udemy.com/go-fintech/

     

     

  • redash パラメータを動的に変えてクエリを実行する

    redash パラメータを動的に変えてクエリを実行する

    Notice!

    以下の記事で redash  のみで行う方法をまとめております。
    こちらの記事をご覧ください。

     

    https://tsukada.sumito.jp/2020/02/28/redash-api-query-parameter/

    はじめに(本記事はサードパーティを利用した方法です)

    redashはとても便利だが、パラメータを動的に変えてクエリを投げる様な事はオフィシャルにはできない

    しかし、それもサードパーティを利用し、少し手を加える事で実現可能になる。

    検証環境の構築

    サンプルをダウンロード

    サンプルのredashと、適当なデータが入ったmysqlをダウンロード

    git clone https://github.com/GitSumito/redash-blue

    セットアップ

    docker-compose run --rm server create_db docker-compose up

    http://localhost/setup

    へ接続するとセットアップ画面が表示されるので入力する

    ログインすると、右上のメニューから Edit Profile を選択する

    API keyが表示されるのでひかえる

    データソースにmysqlを追加する

    設定は以下の通り

     この時、保存した際のURLを確認する

    /data_sources/1 とある。

    これがデータソース番号となる。今回登録したデータソースは1番ということがこれでわかる。

    クエリを書く

    select * from city where CountryCode = "{{code}}"

    このクエリを書くと、下にテキストボックスが表示される

    これでExecuteボタンを押すと、where CountryCode = “JPN” が実施される

    クエリを保存すると、以下の様なURLになっている

    後ろにパラメータがついているがそれは無視すると、クエリ番号1番となっていることがわかる。

     

    /redash_client をインストールする

    https://github.com/mozilla/redash_client

    mozillaでredash clientというものが存在している。

    これを ariarijp さんが改修してくれていた。神!

    (今現在masterに取りこめられていないが、非常に便利な機能だ)

    差分が公開されているので、これを元にオリジナルのmozillaを一部改修する

    https://github.com/mozilla/redash_client/pull/70/files#diff-80f7450d3a8b47a2d0a622873d1a67fe

    これにより、動的クエリを受け付けることができるようになる

     

     

    from pprint import pprint
    
    import os
    import pystache
    
    from redash_client.client import RedashClient
    
    api_key = os.environ["REDASH_API_KEY"]
    
    client = RedashClient(api_key)
    client.BASE_URL = 'http://127.0.0.1/'
    client.API_BASE_URL = client.BASE_URL + 'api/'
    
    query = client.get_query(1)
    sql = pystache.render(query['query'], {
      'code': 'JPN',
    })
    
    result = client.get_query_results(sql, query['data_source_id'])
    
    pprint(result, width=160)

    その後、環境変数に

    REDASH_API_KEY

    をセットする

    export REDASH_API_KEY=*********************

    実行結果

    $ python3 mozilla.py 
    [{'CountryCode': 'JPN', 'District': 'Tokyo-to', 'ID': 1532, 'Name': 'Tokyo', 'Population': 7980230},
     {'CountryCode': 'JPN', 'District': 'Kanagawa', 'ID': 1533, 'Name': 'Jokohama [Yokohama]', 'Population': 3339594},
     {'CountryCode': 'JPN', 'District': 'Osaka', 'ID': 1534, 'Name': 'Osaka', 'Population': 2595674},
     {'CountryCode': 'JPN', 'District': 'Aichi', 'ID': 1535, 'Name': 'Nagoya', 'Population': 2154376},
     {'CountryCode': 'JPN', 'District': 'Hokkaido', 'ID': 1536, 'Name': 'Sapporo', 'Population': 1790886},
     {'CountryCode': 'JPN', 'District': 'Kyoto', 'ID': 1537, 'Name': 'Kioto', 'Population': 1461974},
     {'CountryCode': 'JPN', 'District': 'Hyogo', 'ID': 1538, 'Name': 'Kobe', 'Population': 1425139},

    scriptのcodeを変えて実行

    $ python3 mozilla.py 
    [{'CountryCode': 'USA', 'District': 'New York', 'ID': 3793, 'Name': 'New York', 'Population': 8008278},
     {'CountryCode': 'USA', 'District': 'California', 'ID': 3794, 'Name': 'Los Angeles', 'Population': 3694820},
     {'CountryCode': 'USA', 'District': 'Illinois', 'ID': 3795, 'Name': 'Chicago', 'Population': 2896016},
     {'CountryCode': 'USA', 'District': 'Texas', 'ID': 3796, 'Name': 'Houston', 'Population': 1953631},
     {'CountryCode': 'USA', 'District': 'Pennsylvania', 'ID': 3797, 'Name': 'Philadelphia', 'Population': 1517550},
     {'CountryCode': 'USA', 'District': 'Arizona', 'ID': 3798, 'Name': 'Phoenix', 'Population': 1321045},

    取得結果が変わった。

    色々活用できる場がありそうだ。

     

  • BigQueryのpartitioned-tables(分割テーブル)について

    BigQueryのpartitioned-tables(分割テーブル)について

    はじめに

    BigQueryは従量課金のモデルのため、スキャン量に応じて課金される。

    いかにスキャン対象を減らすかが非常に重要になる。

    通常のwhereで絞ったとしても、スキャンはされてしまうため課金を回避することができない。

    そこで、partitioned-tables(分割テーブル)である。

    partitioned-tables(分割テーブル)について

    現時点で大きく2つ存在している

    • 取り込み時間分割テーブル:
      データを取り込んだ(読み込んだ)日付またはデータが着信した日付に基づいて分割されたテーブル。
    • 分割テーブルTIMESTAMP 列または DATE 列を基準にして分割されたテーブル

    詳細はこちら

    https://cloud.google.com/bigquery/docs/creating-partitioned-tables

    通常のwhereのように使い、課金額を減らすのが目的であれ”取り込み時間分割テーブル”ではなく”分割テーブル”のが便利そうだ

    やってみた

    テーブル定義

    まずはテーブル定義

    [
      {
        "mode": "NULLABLE", 
        "name": "register_day", 
        "type": "STRING"
      }, 
      {
        "mode": "NULLABLE", 
        "name": "rtime", 
        "type": "STRING"
      }, 
      {
        "mode": "NULLABLE", 
        "name": "lesson_date", 
        "type": "TIMESTAMP"
      }
    ]

    テーブルを作成する

    bq mk --table --expiration 3600 --description "This is my table" --time_partitioning_field=lesson_date --time_partitioning_type=DAY --label organization:development logs.cccc bbbb 

    lesson_dateが分割テーブルのパーティションとなる

    読み込み

    データはこんな感じ

    {"register_day":"3320915", "rtime":"tsukada", "lesson_date": "2019-04-30 14:02:04"}
    {"register_day":"3320915", "rtime":"tsukada", "lesson_date": "2019-05-30 14:02:04"}
    {"register_day":"3320915", "rtime":"tsukada", "lesson_date": "2019-06-30 14:02:04"}
    {"register_day":"3320915", "rtime":"tsukada", "lesson_date": "2019-07-30 14:02:04"}

    読み込ませる

    bq load --source_format=NEWLINE_DELIMITED_JSON logs.cccc cccc.json 

    使ってみる

    #standardSQL
    SELECT
      *
    FROM
      logs.cccc
    WHERE  
      lesson_date BETWEEN '2017-01-01' AND '2019-10-01'

    少数のデータなので記事としては微妙だが、最小単位の10Mが課金対象となる。

     

  • gcloud(gcpのコマンド)をzshで使えるようにする

    gcloud(gcpのコマンド)をzshで使えるようにする

    はじめに

    gcloudコマンドしようとすると、デフォルトではbashへinstallすることが前提となってしまっている。

    zshでgcloudコマンドを設定する。

    前提

    gcloudコマンドがinstallされていること。

    まだの場合は公式手順を参考にinstallする。

    https://cloud.google.com/sdk/downloads?hl=ja

    gcloudコマンドのインストール場所を探す

    デフォルトでは “` ~/google-cloud-sdk/ “` にインストールされる

    もし存在しない場合はfindなどで調べる

    .zshrcの設定を変更

    google-cloud-sdk配下に

    “` path.zsh.inc “` というファイルがある。これを.zshrcへ追加する

    source /Users/sumito.tsukada/google-cloud-sdk/path.zsh.inc

    このような感じ。

    その後は再読み込みを実施する

    “` source ~/.zshrc “`

    以上。

     

  • ERROR 1064 (42000) at line 101: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ” at line 1

    ERROR 1064 (42000) at line 101: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ” at line 1

    はじめに

    mysqldumpで取得した結果を、そのままmysqlへ流しこもうとしたらエラーになった。

    実施したコマンド

    変数には適宜設定値が入る。

    やりたいことはmysqldumpでデータを取得し、標準出力で別のサーバへ流し込む。

    mysqldump -u$dbbackupuser $dbbackupname $table -h$dbbackuporiginal -p$dbbackuppass | mysql -u$dbrestoreuser -h$dbrestoreserver -p$dbrestorepass $dbrestorename 

    発生したエラー

    ERROR 1064 (42000) at line 101: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1

    原因

    mysqldumpコマンドはデフォルトでmysqlの独自構文が入ってしまうことがあり、微妙なmysqlのversionの差異がこの独自構文を受け付けないことがある。

    対処

    ANSIフォーマットで出力させるオプション “` –compatible=ansi “` を追加する

     after

    mysqldump --compatible=ansi -u$dbbackupuser $dbbackupname $table -h$dbbackuporiginal -p$dbbackuppass | mysql -u$dbrestoreuser -h$dbrestoreserver -p$dbrestorepass $dbrestorename 

     

  • gitのリポジトリの引越しをする

    gitのリポジトリの引越しをする

    はじめに

    リポジトリが肥大化したり、プロジェクトが大きくなり、サービス名が変わったり、プロジェクトを進めていくといろいろなことがある。

    リポジトリの移行方法をまとめる。

    移行元(gitlab) -> 移行先(gitlabの別プロジェクト

    before projectからgit cloneする

    % git clone --mirror git@git.hoge.com:before/beforeproject.git
    Cloning into bare repository 'beforeproject.git'...
    
    

    移行先のプロジェクトへgit pushを行う

    % git push --mirror git@git.sumito.com:after/afterproject.git
    Counting objects: 1381, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (520/520), done.
    Writing objects: 100% (1381/1381), 266.47 KiB | 88.82 MiB/s, done.
    Total 1381 (delta 629), reused 1381 (delta 629)
    remote: Resolving deltas: 100% (629/629), done.% 

    最後に

    今回はgitlabのプロジェクトからgitlabですが、gitlabからgithubのような場合も同様の手順でいけます。

  • CannotStartContainerError: API error (500): failed to initialize logging driver: failed to create Cloudwatch log stream: ResourceNotFoundException: The specified log group does not exist. status code: 400,

    CannotStartContainerError: API error (500): failed to initialize logging driver: failed to create Cloudwatch log stream: ResourceNotFoundException: The specified log group does not exist. status code: 400,

    はじめに

    fargateでタスクを登録し、起動させた時エラーが発生。原因と対処をまとめる

    An error occurs when a task is registered and started with fargate. Summarize causes and actions

    原因

    CannotStartContainerError: API error (500): failed to initialize logging driver: failed to create Cloudwatch log stream: ResourceNotFoundException: The specified log group does not exist. status code: 400,

    CloudWatch のロググループが存在しない

    CloudWatch log group does not exist

    対処

    CloudWatchにロググループを作成する

    Create a log group in CloudWatch

    その後、再度タスクを実行すれば問題は解消できる。

    After that, the problem can be solved by executing the task again.

     

  • nodeのversion管理をnvmで行う

    nodeのversion管理をnvmで行う

    はじめに

    Linux/Macにてnodeのversion管理を手軽に行うよう、nvmで切り替えれられるようにする

    nvmインストール

    nvmのオフィシャルリポジトリはこちら

    https://github.com/creationix/nvm

    ここに記載があるように、installを行う。

    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash

    ~/.bash_profileに環境変数を追加する

    export NVM_DIR="$HOME/.nvm"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

    変更した~/.bash_profileを読み込む

    source ~/.bash_profile

    stableをインストール

    nvm install stable

    を行うと、stableをインストールすることが可能。

    執筆時のversionは以下の通り

    # node -v
    v11.12.0

    任意のversionをインストール

    nvm ls-remoteコマンドを実施すると、インストール可能なversionが列挙される

    # nvm ls-remote
            v0.1.14
            v0.1.15
            v0.1.16
            v0.1.17
            v0.1.18
            v0.1.19
            v0.1.20
            (略)

    version 8.9.4をインストールする際は以下の通り実施する

    nvm install v8.9.4

    aliasを切り替える

    # nvm alias default v8.9.4
    default -> v8.9.4
    

    version変更を確認

    # node -v
    v8.9.4
    

     

  • mysql 5.7で実行された全クエリをログに出力する

    mysql 5.7で実行された全クエリをログに出力する

    はじめに

    どのようなクエリが実施されたのかトレースする時に使う

    設定

    /etc/my.cnfの設定変更

    general_log=ON
    general_log_file=/var/log/mysqld-query.log

    general_logの記載を追加する

    パーミッション設定

    touch /var/log/mysqld-query.log
    chown mysql:mysql /var/log/mysqld-query.log
    chmod 640 /var/log/mysqld-query.log

    上記設定を入れたら再起動する

    systemctl restart mysqld

    確認

    cat /var/log/mysqld-query.log
    
    2019-03-14T05:39:18.710354Z	    3 Query	INSERT INTO s_bookmark (  id, bookmark_at,