プログラミングでアイデアを具現化したい

仮説アルファを妄想するのが日課でアイデアを具現化するためにプログラミングを始めました。主な言語はC# 。

SSHでPostgresqlに接続した話

趣味プログラマーとして今までノーガード上等でやってきましたがちょっとした事情で
セキュリティを高める必要があって、DBサーバへSSH接続してDBサーバから情報を
クライアントアプリで取得するフローを構築したのでメモ書き。

クラウドにおいてるwinサーバ(DBサーバでもあるw)にOPENSSHをインストールしてサービス開始。
このサイトがわかりやすかった。
https://www.server-world.info/query?os=Windows_Server_2016&p=openssh


②クライアントアプリからのアクセスもSSHに対応させる為、SSH.NETというライブラリを使用。
言語はもちろんC#。なんだかんだで中途半端にC#しかできねぇ
サンプルコードはこのサイトがわかりやすかった。
http://shen7113.blog.fc2.com/blog-category-4.html


サンプルコード
※あくまでサンプルなので、SSHのコネクション閉じないのかとかそーゆう話は別でw

public List<独自クラス> Get独自データ(引数) {
    try {

        var connectionInfo = new PasswordConnectionInfo("winサーバIP", 22, "winサーバユーザ", "パスワード");
        var client = new SshClient(connectionInfo);
        client.Connect(); //SSH接続
       
        var forward = new ForwardedPortLocal("127.0.0.1(localhost)", 63333, "winサーバIP", postgresqlで使うport);
        client.AddForwardedPort(forward);
        forward.Start(); //ポートフォアード開始

        NpgsqlCommand cmd = new NpgsqlCommand("ストアドファンクション名", _connPostgre);
        cmd.Parameters.AddWithValue("ストアドの引数", 引数);
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        _connPostgre.Open();
        var result = cmd.ExecuteReader();
        var hoges  = new List<独自クラス>();
        while (result.Read()) {
            var hoge = new 独自クラス() {
                Name = result.GetValue(0).ToString(),
                Age = result.GetValue(1).ToString(),
            };
            hoges  (hoge );
        }

        return hoges  ;

    }
    catch (Exception ex) {
        Program.logger.Error(ex);
        return new List<独自クラス>();
    }
    finally {
        if (_connPostgre != null)
            _connPostgre.Close();
    }
}


こーゆう実装は今までしたことなかったのでやってみて良かったかもしれない。

アルゴリズム取引の正体


アルゴリズム取引の正体

アルゴリズム取引の正体」を読んだ。


目次
第1章 アルゴリズム取引とは
第2章 アルゴリズム取引の市場環境
第3章 市場取引におけるリターン、リスク、コスト、流動性
第4章 アルゴリズム取引概論
第5章 アルゴリズム取引戦略
第6章 HFT:高頻度取引
第7章 外国為替取引におけるアルゴリズム取引
第8章 アルゴリズム取引の環境の変化と投資家の取組み


2章、3章ではレイテンシー、コストとディーリングシステム構築に無視できない重要なポイントを抑えていたり4章以降では各種アルゴリズムを幅広く解説している。実際に機関ディーリングシステムに関わった事のある方なら目新しい情報はないかもしれないが、システムトレーダー、ディーリングシステム開発者なら目を通しておく教科書のような本だと思う。新入社員が配属されたらまず読ませたい本だ。


私も手元に置いておこうと思い、FIX入門以来かな?めずらしくkindle化されていない本を購入してしまいました。

MT4オフラインチャートの作り方メモ

久々のエントリーです。
今更誰にも需要がなさそうなタイトルですが、作業用メモということで。

手順①
ツール→オプション→プロキシサーバーを有効にチェック
プロキシ設定からサーバーに「offline」を入力してOK。
※通信できなければなんでもいい。
MT4再起動

手順②
以下SQLでエクスポート。(ccyPair、dateTime は都度変更)

SELECT [dateTime],[o_b],[h_b],[l_b],[c_b],10 as vol
  FROM [MarketMonitor].[dbo].[ohlc]
  where [dateTime] between '2017-01-01 07:00:00.000' and '2018-09-01 06:59:00.000'
  and [ccyPair]='USDJPY'
  order by [dateTime]

f:id:tos5511:20180915050111p:plain

※4本値を持っている前提。自分は月1で某社の1分足をSQLServerにぶっこんでます。
おまけでぶっこみコード

static void Main(string[] args) {
    try {
        logger.Info("ohlcをDBに取り込み開始します。");
        string download_folder = ConfigurationManager.AppSettings["download_folder"].ToString();
        string unzip_folder = ConfigurationManager.AppSettings["unzip_folder"].ToString();
        ClearFolder(unzip_folder);
        string[] zipFiles = Directory.GetFiles(download_folder);

        //全てzpiを解凍する
        Console.WriteLine("全てzpiを解凍します。");
        foreach (var zipFile in zipFiles) {
            Unzip(zipFile, unzip_folder);
        }

        //C:\Work以下に*.*のファイルを取得する(サブフォルダすべてが検索対象)
        Console.WriteLine("全てファイルを取得します。");
        string[] strFiles = System.IO.Directory.GetFiles(
            unzip_folder, "*.*", System.IO.SearchOption.AllDirectories);

        var text = string.Format("取得したファイル数は{0}個", strFiles.Length);
        Console.WriteLine(text);

        int count = 0;
        foreach (var file in strFiles) {
            text = string.Format("{0}/{1}", count, strFiles.Length);
            Console.WriteLine(text);

            if (file.Contains("EX")) continue;
            var ccyPair = file.Substring(file.Length - 19,6);

            if (File.Exists(file)) {
                using (var reader = new StreamReader(file, Encoding.GetEncoding("shift_jis"))) {
                    while (!reader.EndOfStream) {
                        var line = reader.ReadLine().Split(',');
                        DateTime dt;
                        if(DateTime.TryParse(line[0], out dt)){
                            OHLC ohcl = new OHLC() {
                                Datetime = dt,
                                CcyPair = ccyPair,
                                o_b = decimal.Parse(line[1]),
                                h_b = decimal.Parse(line[2]),
                                l_b = decimal.Parse(line[3]),
                                c_b = decimal.Parse(line[4]),
                                o_a = decimal.Parse(line[5]),
                                h_a = decimal.Parse(line[6]),
                                l_a = decimal.Parse(line[7]),
                                c_a = decimal.Parse(line[8]),
                            };
                            DBConnection.Provider.InsertOHLC(ohcl);
                        }
                        else {
                            continue;
                        }
                    }
                }
            }
            count++;
        }

        Console.WriteLine("DB取込完了。");
        logger.Info("DB取込完了。");

        Console.WriteLine("作業フォルダをクリアします。");
        ClearFolder(download_folder);
        ClearFolder(unzip_folder);
        Console.ReadKey();
    }
    catch(Exception ex) {
        logger.Error(ex);
    }
}

public static void ClearFolder(string clearPath) {
    DirectoryInfo target = new DirectoryInfo(clearPath);
    //ファイル消す
    foreach (FileInfo file in target.GetFiles()) {
        file.Delete();
    }
    //フォルダも消す
    foreach (DirectoryInfo dir in target.GetDirectories()) {
        dir.Delete(true);
    }
}

public static void Unzip(string file, string unzip_folder) {
    //ZIP書庫を展開する
    System.IO.Compression.ZipFile.ExtractToDirectory(file, unzip_folder, Encoding.GetEncoding("shift_jis"));
}

手順③
出力したcsvからヘッダーを削除(効率悪い?)
ツール→ヒストリーセンター→インポート
f:id:tos5511:20180915050152p:plain

ちゃんと618940レコードインポートされてます。
f:id:tos5511:20180915050210p:plain

手順④
MT4再起動
ファイル→オフラインチャート→CCYPAIR,1Mを選択して開く
f:id:tos5511:20180915050350p:plain

チャートを開いたら、後はスクリプトのPeriodConverterで5,15,30,60,240,1440と
実行すれば1分足から日足までのオフラインチャートが作成されます。
f:id:tos5511:20180915051050p:plain

完成。