barus's diary

とても真面目なblogですにゃ

【BitFlyer】C#でビットコインを自動売買する。その②(時系列データを取得する)

ビットコイン それは現代のゴールドダッシュである・・・云々かんぬん・・( ゚Д゚)

 

さておき、

前回の続きである。タイトルでは、C#ビットコインを自動売買する。と書いたが、ここで、C#で全部作ってしまうか。それともDLL化して、VC++で処理するか、迷うところである。

 

bitFlyer ビットコインを始めるなら安心・安全な取引所で

BitFlyerでアカウントを作成してAPIを利用している。

 

 

それはさておき、時系列のデータを取得できないと、スタンダードな移動平均線などが作成できない。

 

なので、今回は、時系列データを取得するプログラムを紹介する。

 

んが、APIを見ても時系列取得がない。しょうがないからググってみると時系列データを取得するAPIがなさそうだ。

 

( ^ω^)エッ・・・。

 

時系列データ取得できないでどうやって自動売買の判断しろっていうのだろうか?(怒)なんとも中途半端なAPI公開である。

 

( ゚Д゚) ・・・チネ

 

んが、このサイトの紹介で、過去のデータをここのサイトから取得する方法があるらしいのでこれを試してみる。

 

periodsというパラメータで何秒区切りかを指定でき、beforeとafterというパラメータにUNIX timestampを投げることで時間の指定もできる。

1日足で、2017/01/01以降のチャートを取得したい時は以下のような感じ。

https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=86400&after=1483196400

 

以下はBitcoinの時系列データを取得した結果です。(BitFlyerAPIは利用していません。)

f:id:hatakeka:20180105203539g:plain

 

前回のプロジェクトを流用する。

 

完成品は、Vectorに置いています。

 

 

 

まず。外観を以下のようにする。

 

button1

button2

comboBox1

textBox1

textBox2

monthCalendar1

を以下のような感じでツールボックスからドラッグアンドドロップしてペタペタ配置する。

f:id:hatakeka:20180105204353p:plain

monthCalendar1のプロパティのVisibleをfalseにしておく(起動時に非表示にする。)

f:id:hatakeka:20180105215310p:plain

comboBox1にアイテムをセットする。comboBox1の右上にある▼マークをクリック>項目の編集をクリックし

1min
5min
15min
30min
1H
4H
1D
1W

を記入する。

 

f:id:hatakeka:20180105220826p:plain

f:id:hatakeka:20180105221041p:plain

 

外形が決まったら次に、ソースコードを書いていく。

 

Form1.cs  ←今回も修正

Submit.cs   ←前回追加したクラス。今回も修正

WIn32API.cs ←前回追加したクラス。修正なし

Converts.cs     ←今回追加したクラス

ErrorClass.cs    ←今回追加したクラス

 

以下のような感じとなる。

f:id:hatakeka:20180107104818p:plain

 

 Form1.cs ソースコード

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;



namespace C_BitCoin
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Submit tes = new Submit();

            string url = getUrlPath_cryptowat();
            if (url.Equals("err")==false)
            textBox1.Text = tes.testcall("https://api.cryptowat.ch", url).ToString();


        }

        private string getUrlPath_cryptowat()
        {
            ErrorClass err = new ErrorClass();
            ConvertsEctx conver = new ConvertsEctx();
            string url_base = "/markets/bitflyer/btcjpy/ohlc?periods=";

            if (comboBox1.Text.Length == 0) { err.errmes("時間間隔を入力してください。"); return "err"; }
            if (textBox2.Text.Length == 0) { err.errmes("日付を入力してください。"); return "err"; }

            url_base += getPeriods(comboBox1.Text);

            url_base += "&after=";

            url_base += conver.ToUnixTime(DateTime.Parse(textBox2.Text)).ToString();

            return url_base;
        }

        //-------------------------------------
        //コンボボックスの時間を秒数に変換
        //-------------------------------------
        private string getPeriods(string txt)
        {
            string rlt = "";
            if (txt.Equals("1min")) rlt = "60";
            if (txt.Equals("5min")) rlt = "300";
            else if (txt.Equals("15min")) rlt = "900";
            else if (txt.Equals("30min")) rlt = "1800";
            else if (txt.Equals("1H")) rlt = "3600";
            else if (txt.Equals("4H")) rlt = "14400";
            else if (txt.Equals("1D")) rlt = "86400";
            else if (txt.Equals("1W")) rlt = "604800";

            return rlt;
        }

        //-------------------------------------
        //カレンダー表示
        //-------------------------------------
        private void button2_Click(object sender, EventArgs e)
        {
            monthCalendar1.Visible = (monthCalendar1.Visible==true) ? false: true;
        }

        //-------------------------------------
        //カレンダーの日付をtextbox2にセットする
        //-------------------------------------
        private void monthCalendar1_DateChanged(object sender, DateRangeEventArgs e)
        {
            string str = monthCalendar1.SelectionRange.End.ToString();
            string[] str2 = str.Split(' ');
            textBox2.Text = str2[0];
        }
    }

    
}

Submit.cs  ソースコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows.Forms; //Application
using System.Net.Http;
using System.Net.Http.Headers;


namespace C_BitCoin
{
    class Submit
    {

        //static readonly Uri endpointUri = new Uri("https://api.bitflyer.jp");
       
        public static string _rlt_response;

        public string testcall(string endpointurl, string getcommand)
        {
            Task t = test(endpointurl, getcommand);


            bool endflag = true;
            int cnt = 0;
            //レスポンスを待つ
            while (endflag)
            {

                endflag = (_rlt_response == null) ? true : false;
                Stoptime(100);
                cnt++;
                if (cnt > 100) break;
            }
            return _rlt_response;

        }

        public static async Task test(string endpointurl, string getcommand)
        {

            var method = "GET";
            var path = getcommand; //"/v1/ticker";
            var query = "";

            using (var client = new HttpClient())
            using (var request = new HttpRequestMessage(new HttpMethod(method), path + query))
            {
                Uri endpointUri = new Uri(endpointurl);
                client.BaseAddress = endpointUri;
                var message = await client.SendAsync(request);
                var response = await message.Content.ReadAsStringAsync();

                _rlt_response = response.ToString();
                Console.WriteLine(response);

            }

        }

        public static void Stoptime(long st)
        {
            long lngst;
            lngst = Win32API.timeGetTime();
            while (Win32API.timeGetTime() - lngst < st)
            {
                Application.DoEvents();
            }
        }
    }
}

WIn32API.cs ソースコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Runtime.InteropServices;// DllImportに必要

using System.Windows;


namespace C_BitCoin
{

    class Win32API
    {
        //時間
        [DllImport("winmm.dll", EntryPoint = "timeGetTime")]
        public static extern long timeGetTime();
        
    }

}

Converts.cs     ソースコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace C_BitCoin
{
    class ConvertsEctx
    {
        private static readonly DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        //指定時間をUnixTimeに変換する.
        public long ToUnixTime(DateTime dt)
        {
            double nowTicks = (dt.ToUniversalTime() - UNIX_EPOCH).TotalSeconds;
            return (long)nowTicks;
        }

        // UnixTimeからDateTimeに変換.
        public DateTime ToDataTime(long unixTime)
        {
            return UNIX_EPOCH.AddSeconds(unixTime).ToLocalTime();

        }

        //現在の時間をUnixTimeに変換する
        public long Now()
        {
            return (ToUnixTime(DateTime.UtcNow));
        }

    }
}

ErrorClass.cs    ソースコード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows.Forms;

namespace C_BitCoin
{
    class ErrorClass
    {
        public void errmes(string messtr)
        {
            MessageBox.Show(messtr,
            "エラー",
            MessageBoxButtons.OK,
            MessageBoxIcon.Error);
        }
    }
}

以上より。

F5などで、ビルドすると以下のような感じになる。

f:id:hatakeka:20180105203539g:plain

 

 

getUrlPath_cryptowat()関数でurlを組み立てている。

もう一度、定義を見てみると以下。

periodsというパラメータで何秒区切りかを指定でき、afterというパラメータにUNIX timestampを投げることで時間の指定もできる。

https://api.cryptowat.ch/markets/bitflyer/btcjpy/ohlc?periods=86400&after=1483196400 

これより、Periodsに入る値は、getPeriods()関数にてコンボボックスのそれぞれの時間から秒数に変換し。afterに入る値は、textbox2に入った日付をToUnixTime()関数にてUNIX timestampに変換している。

 

 

 

BitFlyerAPIは公開されていないので、別サイトから時系列データを取得したのだが、この取得したデータと、BitFlyerの時系列データと一致するかどうかは不明。なので、自己責任で利用お願い致します。( ゚Д゚)

 

 

 

以上。

 

参考URL

bitFlyerの過去チャートを取得するAPI - shobylogy

C#でUnixTimeを扱う - YuukTsuchida's blog

C# - 文字列から DateTime の値に変換する