Creating an API to real-time calculate Bitcoin arbitrage rate of return

The strict regulation on Know Your Customer (KYC) and Anti Money-Laundering (AML) policies in Korea is creating a strong and consistent arbitrage opportunity using Bitcoin. This blog post will talk about how I created an API that calculates the arbitrage rate of return real-time. An article says:

The South Korean bitcoin exchange has presented excellent arbitrage opportunities for traders. South Korean bitcoin exchange have always demonstrated a high premium on their listed bitcoin prices and trading rates.

The strategy goes like this:

  • Step 1. Sell USD, buy Bitcoin (in an exchange of your preference)
  • Step 2. Sell Bitcoin, buy KRW in Korbit (an exchange)
  • Step 3. Sell KRW, buy USD.

It'd be cumbersome to get exchange rates from multiple exchanges and calculate an arbitrage return every time. Instead, this blog presents a way to build an API that automatically calculates the arbitrage return for you using Knowru. The service is publicly available so you can use it as well (see this page (ID: demo, PW: KnowruForAPI!)).

As of June 16, 2017, an arbitrage opportunity still existed.


The purpose of the material here is to show how easy it is to create, customize, maintain and use APIs using Knowru. Though the trading strategy here is based on a realistic scenario, you should take the material as a fun, interesting reading rather than a serious, professional article on trading and Bitcoin.

Step 1. Write a script that calculates the rate of return

I got the latest exchange rates for the the three steps as below:

In essence, I combined these three APIs that return exchange rates real-time to calculate the arbitrage rate of return. I am using Python 2.7 and created a virtual environment to manage packages.

~/$ mkdir bitcoin_krw_arbitrage
~/$ cd bitcoin_krw_arbitrage
~/bitcoin_krw_arbitrage$ virtualenv env
~/bitcoin_krw_arbitrage$ source env/bin/activate
~/bitcoin_krw_arbitrage$ pip install requests
~/bitcoin_krw_arbitrage$ pip install xmljson
~/bitcoin_krw_arbitrage$ pip freeze > requirements.txt

I created a script named and wrote a function named calculate_rate_of_return. The function gets base currency code and amount as an input, calculates a rate of return from the 3 APIs above and then return the outcome.

import requests
from xmljson import BadgerFish
from xml.etree.ElementTree import fromstring

def get_exchange_rate(base_currency_code, foreign_currency_code):
    url = '{}&symbols={}'.format(base_currency_code, foreign_currency_code)
    response = requests.get(url)
    return response.json()['rates'][foreign_currency_code]

def calculate_rate_of_return(base_currency_code, base_amount):
    # Step 1. Get bitcoin amount
    blockchain_api_url = "{}&value={}".format(base_currency_code, base_amount)
    bitcoin_amount = float(requests.get(blockchain_api_url).text)
    # More information can be found here:

    # Step 2. Sell the Bitcoin and buy KRW in Korbit
    korbit_api_url = ""
    korbit_krw_exchange_rate = float(requests.get(korbit_api_url).json()["last"])
    krw_amount = bitcoin_amount * korbit_krw_exchange_rate
    # More information can be found here:

    # Step 3. Sell KRW and buy USD (or base currency)
    # Step 3 - 1. Get exchange rate between KRW and USD from Yahoo finance API
    krw_base_exchange_rate = get_exchange_rate("KRW", base_currency_code)

    # Step 3 - 2. Get USD amount (or base currency amount)
    repurchased_base_amount = krw_amount * krw_base_exchange_rate

    # Step 4. Calculate the rate of return
    rate_of_return = (repurchased_base_amount - base_amount) / base_amount

    return_dict = {
        "base": {
            "base_currency_code": base_currency_code
            , "base_amount": round(base_amount, 4)
        }, "step1_buy_bitcoin": {
            "base/bitcoin_exchange_rate": round(bitcoin_amount / base_amount, 4)
            , "bitcoin_amount": round(bitcoin_amount, 4)
        }, "step2_buy_krw": {
            "bitcoin/krw_exchange_rate": round(korbit_krw_exchange_rate, 4)
            , "krw_amount": round(krw_amount, 4)
        }, "step3_buy_base": {
            "krw/base_exchange_rate": round(krw_base_exchange_rate, 4)
            , "repurchased_base_amount": round(repurchased_base_amount, 4)
        }, "rate_of_return": round(rate_of_return, 4)
    return return_dict

Step 2. Write a script named that has a function named run which calls the calculation function

In order to create an API inside Knowru, we need a file named which has a function named run, any other necessary file and requirements.txt that lists required packages and their versions (in case of R, packrat.lock). We already have secured requirements.txt from Step 1. Furthermore, because we already have the rate of return calculation logic, writing is very simple:

from bitcoin_krw_arbitrage import calculate_rate_of_return

def run(data):
    base_currency_code = data.get("base_currency_code", "USD")
    base_amount = data.get("base_amount", 1)
    return calculate_rate_of_return(base_currency_code, base_amount)

Step 3. Login to Knowru

Sign up to Knowru is very easy, only requiring your email address and password. Let us create an account and log in.

Signing up only requires a username, email address and password.
Singing in is easy too.

Step 4. Upload the prepared files

Once logged in, click the "Create" button in the runnable list page. Give a title, choose "Python 2.7" for the language and then choose the three files we prepared:, and requirements.txt.

Click the "Deploy A Model" button on the bottom right.
Enter a title and choose "Python 2.7" for the language.
Choose the prepared files.

In the backend, the Knowru platform prepares necessary hardware configuration to create an API for Basically, every time a request is made to an API, the Knowru platform calls run function inside with the data from the request.

Click the Title to move to the deployed model page. You will see something like below.

The Activity Overview graph of the detail view
Information about the API in the detail view

Step 5. Make the first request

Let us make our first run request by clicking the "Run" button on the right bottom and provide a value like below:
"Run" button
Example input; it comes from how we wrote
In the run list view, click the name of the run to see the result.
Let us click the name of a run to see more details.
It worked!

(Optional) Step 6. Change the input JSON schema

Let us go back to the model detail page. We see these two new sections that did not exist before our first run request.
Automatically created GUI for the API - now, we can enter values and click the "Run" button instead of creating a JSON input to run the API.
Automatically created API documentation - we do not have to type anything when communicating our APIs to someone else.

Because the API will be available to the public for demo purpose, I wanted to make sure that before requests hit, their input are all validated (i.e. conform to a specification). I could easily do that using the platform. First click the "Edit JSON Schema" button on the bottom right of the page and change the values like below:

Edit JSON Schema Form
# Input json schema
# Before
    "properties": {
        "base_amount": {
            "type": "integer"
        "base_currency_code": {
            "type": "string"
    "required": [
    "type": "object"

# After
# base_amount and base_currency_code are not required
# Only the following currency codes are supported at all three exchange steps: USD, ISK, HKD, TWD, CHF, EUR, DKK, CLP, CAD, INR, CNY, THB, AUD, SGD, KRW, JPY, PLN, GBP, SEK, NZD, BRL, RUB
# base_amount should be greater than 0

    "properties": {
        "base_currency_code": {
            "type": "string"
            , "enum": ["USD", "ISK", "HKD", "TWD", "CHF", "EUR", "DKK", "CLP", "CAD", "INR", "CNY", "THB", "AUD", "SGD", "KRW", "JPY", "PLN", "GBP", "SEK", "NZD", "BRL", "RUB"]
        "base_amount": {
            "type": "number"
            , "minimum" 0
            , "exclusiveMinimum": true
    "type": "object"

Then, we can see that the Auto GUI section automatically changes to only accept one of the available currency codes.

Auto GUI automatically changes the text input field to a select input field for the variable Base Currency Code after the input JSON schema is changed.

Let us make the API to validate input before the input goes to First click the "Edit" button and then change the "Validate input" from False to True.

Change the field "Validate input" from False to True will validate every input data before it goes to

Step 7. Open it to the world

As of now, the model is not visible to anyone else other than yourself. If you want to share the model with the public, you can change the "Is public" property from False to True in the model edit form.
With "is public" False, a user requires both authentication and authorization to access your model; with "is public" True, an anonymous user can take a look and benefit from using your model.

How does Knowru help us build the API

Benefit 1. We do not have to worry about infrastructure

Knowru automatically takes care of all the hassle of moving files to the cloud environment, auto-scale up and down, checking authorization and etc.

Benefit 2. It validates an input using a JSON schema

Because our API is exposed to the public, we want to check whether people are not sending any non-comforming data. Writing all the input validation code in our script will require at least some lines of code (checking type, range and possible values). Knowru does this for us.

Benefit 3. It created a GUI for me

Not only is the GUI automatically generated, but also it is mobile-responsive!

Mobile-responsive Auto GUI

Benefit 4. It creates an API documentation

When communicating our API, we do not have to write any documentation - Knowru created one for us.

Please access this page to try yourself (ID: demo, PW: KnowruForAPI!). If you have any question, contact us by clicking the button below or sending an email to

Related blog posts

(Header image courtesy of

Receive notices on new features, blog posts and so many more!