Nếu bạn có tài khoản của sàn  Bitfinex và thường hay giao dịch tiền điện tử trên sàn này, bạn có nghĩ có cách nào mà ko phải vào trang web Bitfinex, không cần login mà vẫn lấy được số dư tài khoản, hay tự động thực hiện giao dịch không. Tất nhiên là sẽ có cách, nhưng đòi hỏi rất nhiều thao tác kiểm tra. Thậm chí nếu bạn muốn lấy 1 danh sách lịch sử giá của cặp tiền bitcoin-usd, điều đó cũng là một khó khăn, vì dữ liệu giao dịch trên sàn liên tục được update theo giây, thậm chí là mili giây, cho thấy lượng dữ liệu rất nhiều. Nên nếu bạn có muốn lấy lịch sử dữ liệu của tiền điện tử, bạn cũng chỉ lấy được ở 1 khoảng thời gian nhỏ, và độ phân giản cung bật của giá là theo ngày. Đây là một điểm hạn chế. Chính vì vậy đã có 1 bác viết sẵn api bằng python, giúp bạn có thể lấy được lịch sử ở độ phân giải tầm 1 phút. Bây giờ mình sẽ giới thiệu cách sử dụng bộ api này.

I . CHUẨN BỊ MÔI TRƯỜNG

Mình sẽ dùng vagrant để startup nhanh một con server ubuntu. Bạn nào chưa biết vagrant thì tìm hiểu trên mạng để cài đặt nhé (nôm na thì nó là một tool mạnh mẽ giúp bạn setup nhanh một con máy ảo tích tắc vài phút, thay vì như ngày xưa chúng ta phải ngồi download mấy cái file iso nặng nề về rồi ngồi setup rất mất thời gian).

$ vagrant init bento/ubuntu-16.04
$ vagrant up --provider virtualbox

Truy cập vào server ubuntu

$ vagrant ssh

Chuyển qua quyền root

$ sudo su -

Update và nâng cấp version

$ apt-get update
$ apt-get -y upgrade 

Kiểm tra python đã được cài thành công chưa

$ python -V
Python 2.7.12

Cài thêm 2 tool để hỗ trợ việc setup môi trường

$ apt-get install python-pip
$ apt-get install git

Bây giờ chúng ta lấy code api về máy. Nếu bạn muốn biết thêm về apis của Bitfinex, thì tham khảo ở đây nhé. Chúng ta sẽ dùng git để clone code về

$ git clone https://github.com/akcarsten/bitfinex_api.git
$
$ # Di chuyển vào thư mục source code
$ cd bitfinex_api

Cài đặt module Bitfinex vào môi trường python. Module này đã được viết sẵn, chúng ta chỉ cần cài đặt và sử dụng thôi.

$ pip install -r requirements.txt

II . SỬ DỤNG API CLIENT

Nếu bạn xem tài liệu API của Bitfinex, bạn sẽ thấy có hai phiên bản API là v1 và v2. Bạn yên tâm vì cả hai đều đã được tích hợp vào gói API bạn vừa cài rồi. Ở demo này, chúng ta sẽ demo trên API v2.
Đầu tiên chúng ta sẽ vào môi trường python

$ python
# bạn import gói bitfinex vào để sử dụng
import bitfinex

# tạo một instance từ api v2
api_v2 = bitfinex.bitfinex_v2.api_v2()

# output: No keys, only access to public API functions

Và api_v2 chính là cánh cổng để truy cập đến các hàm trong api và lấy được dữ liệu mong muốn. Cái dòng chữ “No keys, only access to public API functions” chỉ là thông báo bạn khởi tạo instance không kèm theo cặp key public vs secrete. Nếu bạn chỉ đơn thuần muốn lấy những thông tin public như giá thì không cần key. Nhưng nếu bạn muốn lấy số dư tài khoản của mình trên sàn Bitfinex or thực hiện tự giao dịch thì tất nhiên là cần cặp key nhé. Mỗi tài khoản sẽ có cặp key riêng nhé.

Nếu bạn này từng giao dịch mua bán các cặp tiền, hẳn bạn đã từng nghe nói đến biểu đồ nến. Trong biểu đồ nếu sẽ có những thông như thời gian mở (Open), thời gian đóng (Close), giá cao (High), giá thấp (Low), hay trade volume. Chúng được gọi tắt là dữ liệu OHLC. Để lấy được dữ liệu ấy, rất đơn giản, chúng tả chỉ cần gọi đến hàm sau:

result = api_v2.candles()

Dữ liệu đã được trả về biến result. Chúng ta xem thử dữ liệu trả về thuộc kiểu gì nhé.

type(result)

# output: <type 'list'>

Nó là kiểu list. Chắc dữ liệu cũng nhiều, nên chúng ta in thử 5 dòng đầu xem dữ liệu như thế nào.

result[:5]

# output:
#[	[1550485260000, 3811.3, 3811.4, 3811.4, 3811.3, 0.391657],
#	[1550485200000, 3807.6, 3811.3, 3811.3, 3807.5, 14.013301330000001],
#	[1550485140000, 3823, 3807.5, 3823, 3793.98703872, 285.09024547],
#	[1550485080000, 3823, 3823, 3823, 3823, 6.59320366],
#	[1550485020000, 3824.9851437, 3823, 3824.9851437, 3823, 10.87479671]
#]

Những con số này có ý nghĩa gì đây.
Theo tài liệu mô tả ở đây https://docs.bitfinex.com/v2/reference#rest-public-candles thì từng cột sẽ tương ứng là [ MTS, OPEN, CLOSE, HIGH, LOW, VOLUME ]

  • MTS: mili giây
  • OPEN: giá đầu tiên được giao dịch trong khung thời gian
  • CLOSE: giá cuối cùng được giao dịch trong khung thời gian
  • HIGH: giá giao dịch cao nhất trong khung thời gian
  • LOW: giá giao dịch thấp nhất trong khung thời gian
  • VOLUME: lượng giao dịch trong khung thời gian

Bạn nào muốn hiểu rõ hơn về những thông số trên thì các bạn có thể tìm đến các tài liệu về giao dịch FX, chứng khoán để đọc thêm, nó thiên về những từ vựng trong tài chính hơn.

Quay lại với hàm candles() của chúng ta. Hàm đấy sẽ trả về cho bạn dữ liệu của 1000 phút mới nhất về giá của bitcoin-usd. Nếu bạn muốn điều chỉnh về khung thời gian, hay cặp tiền khác, hay độ phân giải về mặt thời gian (vd như lấy phân giải 3h), bạn có thể viết như sau:

import datetime
import time
 
# khai báo tên cặp tiền tệ
pair = "btcusd"

# khai báo độ phân giải về mặt thời gian 
# 1m, 5m, 15m, 30m, 1h, 3h, 6h, 12h, 1D, 7D, 14D, 1M
bin_size = "3h" 

# get maximum 1000 records
limit = 1000

# set thời gian bắt đầu trong khung giờ muốn xem giá - 2018-4-1
t_start = datetime.datetime(2018, 4, 1, 0, 0)
t_start = time.mktime(t_start.timetuple()) * 1000

# set thời gian kết thúc trong khung giờ muốn xem giá - 2018-4-2
t_stop = datetime.datetime(2018, 4, 2, 0, 0)
t_stop = time.mktime(t_stop.timetuple()) * 1000


# request lấy dữ liệu về
result = api_v2.candles(symbol=pair, interval=bin_size, limit=limit, start=t_start, end=t_stop)

Như vậy đoạn code trên sẽ trả về list giá trong ngày đầu tiên của tháng 4 với độ phân giải là 3h (3 giờ).

III . TRUY VẤN DỮ LIỆU TRONG THỜI GIAN DÀI

Bây giờ thật tuyệt nhưng vẫn còn một vấn đề là API sẽ chỉ trả lại tối đa 1000 điểm dữ liệu (1000 records). Vì vậy, nếu tăng khoảng thời gian lên tầm 30 ngày, tức toàn bộ tháng 4 năm 2018 và lấy list giá ở độ phân giải là 1 phút thì điều này là khó có thể. 

Vì vậy, để vượt qua giới hạn này, chúng ta có thể chia nhỏ các truy vấn và nối dữ liệu lại với nhau.

def fetch_data(start, stop, symbol, interval, tick_limit, step):
    api_v2 = bitfinex.bitfinex_v2.api_v2()
    data = []
    start = start - step
    while start < stop:
        start = start + step
        end = start + step
        res = api_v2.candles(symbol=symbol, interval=interval, limit=tick_limit, start=start, end=end)
        # nối dữ liệu lại với nhau
        data.extend(res)
        time.sleep(2)
    return data

Ở hàm trên, bạn sẽ thấy có đoạn time.sleep(2) . Mục tiêu thêm thời gian nghỉ là để giảm số lượng request liên tục gọi đến API thôi.

Các param start, stop thì như ở bước trên.

symbol là cặp tỉ giá.
interval là độ phân giải giá
tick_limit là số điểm giá muốn lấy, tối đa là 1000 điểm giá (1000 records)
step là khoảng thời gian cho một lần request api, nó loop liên tục đến thời gian stop. Ví dụ ở đây chúng ta muốn lấy độ phân giải giá là ‘1m’, mà max điểm giá của chúng ta có thể lấy là 1000 điểm, nên suy ra ta có step = 6010001000 = 60000000 (1m tương đương với 60s, nhưng đơn vị là milisecond, nên nhân thêm với 1000, còn 1000 kìa là max 1000 điểm giá)

Và bây giờ chúng ta chỉ cần khai báo các thông tin như bước trên để truy vấn thông tin giá trong thời gian dài.

# Set step size
time_step = 60000000

# định nghĩa start date 
t_start = datetime.datetime(2018, 4, 1, 0, 0)
t_start = time.mktime(t_start.timetuple()) * 1000

# định nghĩa end date
t_stop = datetime.datetime(2018, 5, 1, 0, 0)
t_stop = time.mktime(t_stop.timetuple()) * 1000

# lấy dữ liệu về, bước này có thể hơi mất thời gian vì phải chờ lấy lượng dữ liệu lơn
pair_data = fetch_data(start=t_start, stop=t_stop, symbol=pair,
                       interval=bin_size, tick_limit=limit, 
                        step=time_step)

Nếu bạn nào đã làm việc với bigdata, hẳn sẽ biết về Pandas. Nếu chưa biết, thì bạn có thể hiểu nôm na là nó là một module hỗ trợ bạn làm việc với list dữ liệu dài trở nên đơn giản hơn như muốn thêm cột, xoá cột, đổi tên v.v...

Dữ liệu từ API trả về chỉ là một list các thông tin giá, thậm chí tên cột dữ liệu còn không có, như vậy thật khó làm việc. Nên giờ ta dùng Pandas để biến list dữ liệu đó như một table mà đc truy vấn từ SQL, có tên cột, muốn thêm xoá sửa gì cũng đơn giản.

# import gói pandas vào để sử dụng
import pandas as pd

# Tạo list tên cột tưng ứng với thứ tự ý nghĩa trong list dữ liệu giá được trả về từ API
names = ['time', 'open', 'close', 'high', 'low', 'volume']

# tạo dataframe (trong pandas gọi là dataframe, bạn nào chưa biết thì hiểu đại khái là tạo bảng dữ liệu)
df = pd.DataFrame(pair_data, columns=names)

# đánh index cho dễ tìm kiếm
df.set_index('time', inplace=True)

# sắp xếp dữ liệu theo cột đã đánh index - là cột thời gian
df.sort_index(inplace=True)

IV . KẾT LUẬN

Như vậy, việc truy xuất dữ liệu OHLC độ phân giải cao thực sự không quá phức tạp. Và nếu bạn tự hỏi có bao nhiêu cặp tiền tệ thì bạn cũng có thể dùng hàm dưới đây để xem

api_v1 = bitfinex.bitfinex_v1.api_v1()
pairs = api_v1.symbols()

Hay nếu bạn muốn xem chính số dư của tài khoản mình trên sàn Bitfinex, bạn cũng có thể đấy:

key = 'YOUR_PUBLIC_KEY'
secrete = 'YOUR_SECRETE_KEY'

api = bitfinex.api_v1(key, secrete)
my_balance = api_bitfinex.balance()

Để mở rộng hơn, các bạn tham khảo thêm trên tài liệu API của Bitfinex nhé.

V . THAM KHẢO

  • https://docs.bitfinex.com/v2/docs
  • https://github.com/akcarsten/bitfinex_api