[PYTHON] I was in vain because I couldn't get a send parent order with pybitflyer

Introduction

It is said that four special orders can be placed with the bitflyer API.

order_method:How to order. Specify one of the following values. If omitted, the value is"SIMPLE"is.
"SIMPLE":This is a special order that places one order.
"IFD":Place an IFD order. An ordering method in which two orders are placed at a time and the second order is automatically placed when the first order is filled.
"OCO":Place an OCO order. This is an ordering method in which two orders are placed at the same time, and when one order is completed, the other order is automatically canceled.
"IFDOCO": IFD-Place an OCO order. An ordering method in which an OCO order is automatically placed after the first order is filled.

Quoted from below https://lightning.bitflyer.com/docs

There is a package called pybitflyer that is convenient for calling the bitflyer API with python. (You can install it with pip.) I'm talking about wanting to place the above special order using this package. https://github.com/yagays/pybitflyer

Preparation

Import the required packages. Prepare API_KEY and API_SECRET in separate files.

import time 
import pybitflyer
import configparser
import json 
import requests

config = configparser.ConfigParser()
config.read('./config.txt')
API_KEY = config['bf']['api_key']
API_SECRET = config['bf']['api_secret']

api = pybitflyer.API(api_key=API_KEY,api_secret=API_SECRET)

※Notes

Below, if API_KEY and API_SECRET are set correctly, the order may be accepted. Please note that we are not responsible for any loss.

Failure example

The function that places a special order is "send parent order". For the parameters, use the following sample as it is. https://lightning.bitflyer.com/docs The type of special order is "IFDOCO".

api.sendparentorder(
    {
  "order_method": "IFDOCO",
  "minute_to_expire": 10000,
  "time_in_force": "GTC",
  "parameters": [{
    "product_code": "BTC_JPY",
    "condition_type": "LIMIT",
    "side": "BUY",
    "price": 30000,
    "size": 0.1
  },
  {
    "product_code": "BTC_JPY",
    "condition_type": "LIMIT",
    "side": "SELL",
    "price": 32000,
    "size": 0.1
  },
  {
    "product_code": "BTC_JPY",
    "condition_type": "STOP_LIMIT",
    "side": "SELL",
    "price": 28800,
    "trigger_price": 29000,
    "size": 0.1
  }]
})
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-19-2b96f6a935f1> in <module>
     24     "price": 28800,
     25     "trigger_price": 29000,
---> 26     "size": 0.1
     27   }]
     28 })

TypeError: sendparentorder() takes 1 positional argument but 2 were given

→ I get angry when the argument is wrong

Success story

I found that the cause was that it was included in the dictionary from the part above parameters. The sample of the bitflyer document is a sample when you hit the API directly without using pybitflyer. As a proof of that, if you hit the API directly with the sample of the bitflyer document as it is, the order will pass.

api.sendparentorder(
  order_method =  "IFDOCO",
  minute_to_expire = 10000,
  time_in_force = "GTC",
  parameters = [{
    "product_code": "FX_BTC_JPY",
    "condition_type": "LIMIT",
    "side": "BUY",
    "price": 900000,
    "size": 0.01
  },
  {
    "product_code": "FX_BTC_JPY",
    "condition_type": "LIMIT",
    "side": "SELL",
    "price": 950000,
    "size": 0.01
  },
  {
    "product_code": "FX_BTC_JPY",
    "condition_type": "STOP_LIMIT",
    "side": "SELL",
    "price": 800000,
    "trigger_price": 810000,
    "size": 0.01
  }]
)
{'parent_order_acceptance_id': 'JRF20200114-110537-710593'}

If it is an API direct order, you can paste the sample as it is (although I changed it to FX_BTC_JPY because I do not have the funds)

def order(side,price,size):
    base_url = "https://api.bitflyer.jp"
    path_url = "/v1/me/sendparentorder"
    method = "POST"
    api_key = API_KEY
    api_secret = API_SECRET

    timestamp = str(datetime.datetime.today())
    
    params = {
      "order_method": "IFDOCO",
      "minute_to_expire": 10000,
      "time_in_force": "GTC",
      "parameters": [{
        "product_code": "FX_BTC_JPY",
        "condition_type": "LIMIT",
        "side": "BUY",
        "price": 920000,
        "size": 0.1
      },
      {
        "product_code": "FX_BTC_JPY",
        "condition_type": "LIMIT",
        "side": "SELL",
        "price": 1000000,
        "size": 0.1
      },
      {
        "product_code": "FX_BTC_JPY",
        "condition_type": "STOP_LIMIT",
        "side": "SELL",
        "price": 900000,
        "trigger_price": 890000,
        "size": 0.1
      }]
    }
    
    body = json.dumps(params)

    message = timestamp + method + path_url + body
    signature = hmac.new(bytearray(api_secret.encode('utf-8')), message.encode('utf-8') , digestmod = hashlib.sha256 ).hexdigest()

    headers = {
        'ACCESS-KEY' : api_key,
        'ACCESS-TIMESTAMP' : timestamp,
        'ACCESS-SIGN' : signature,
        'Content-Type' : 'application/json'
    }

    response = requests.post( base_url + path_url , data = body , headers = headers)
    print( response.status_code )
    print( response.json() )

orderprice = decideOrderPrice("BUY")
order("BUY",orderprice,0.01)
{'parent_order_acceptance_id': 'JRF20200114-110537-710593'}

In addition, unsolved thing

The special order "SIMPLE" is the same understanding as the send child order, but I get angry when I try to do "SIMPLE" with the send parent order. I'm using sendchild order because it passes in a good mood.

api.sendparentorder(
    order_method = "SIMPLE",
    minute_to_expire = 10000,
    time_in_force =  "GTC",
    parameters = [
        {
            #IFD: Buy order at limit price, OCO order when executed
            "product_code": "FX_BTC_JPY",
            "condition_type": "LIMIT",
            "side": "BUY",
            "price": 900000,
            "size": 0.1
        }]
)
{'status': -101, 'error_message': 'Invalid type of order', 'data': None}

Impressions

When I think about it calmly, I can't pass it because I input the sample BODY directly from the API into the wrapper as it is. However, I posted it with the hope that it would help people who are in trouble because they cannot issue send parent orders in the same way.

Future outlook

We have created a BOT that uses REST API for the order part and WEBSOCKET for contract status confirmation and price acquisition, and are testing it on AWS. Random numbers determine whether to buy or sell entries. Now that I know how to order and how to keep ordering, I will concentrate on thinking about the logic to decide the entry. I also think that I can reduce the number of REST APIs because I can issue send parent orders. I feel that the REST API is slow as a bottleneck.

Recommended Posts

I was in vain because I couldn't get a send parent order with pybitflyer
I get a UnicodeDecodeError in mecab-python3
I get a KeyError in pyclustering.xmeans
A story I was addicted to trying to get a video url with tweepy
[Python] Get the files in a folder with Python
When I get a chromedriver error in Selenium
I get a UnicodeDecodeError when running with mod_wsgi
[PyTorch] I was a little lost in torch.max ()
I want to transition with a button in flask
I get a java.util.regex.PatternSyntaxException when splitting a string in PySpark
I was addicted to scraping with Selenium (+ Python) in 2020
I want to work with a robot in python.
I can't manipulate iframes in a page with Selenium
I made a class to get the analysis result by MeCab in ndarray with python
What I was addicted to when dealing with huge files in a Linux 32bit environment
I can't send emails from Lambda in a VPC with Boto3 using a VPC endpoint for SES
I made a simple typing game with tkinter in Python
I was in trouble because the character string in the PDF was strange
A word that I was interested in as a programming beginner
I tried "How to get a method decorated in Python"
Process the files in the folder in order with a shell script
I tried to get started with Hy ・ Define a class
Until I return something with a line bot in Django!
I wrote a script to get a popular site in Japan
I made a puzzle game (like) with Tkinter in Python