どんな記事?
自分でFXのBOTを作成するにあたりOANDA API V20のテストを行いました。それに伴って集めた情報とテストの備忘録(OANDAのBOT作成に必要なすべての情 報)をここにまとめます。主に自分用ですが、一部の人にとっては大変役に立つ情報だと思います。
Twitterでも紹介していただいています
Pythonにしかできないこと
- 機械学習を活用する
- ファンダメンタル等の外部データの参照
- MQL4単体ではできないデータ分析(優位性を探しやすい)
- 複数銘柄でリスク分散するロジック
このあたりがPythonのメリットだと考える。
厳密にはMQL4でもできることも含まれている。しかし、ほとんどのケースでPythonの方がやりやすい。一方でMQL4には、トレードに特化している(必要な機能がパッケージ化されている)というメリットもある。
何よりも自由であることが最大のメリット。
参考
今回のテストを行うにあたって参考にした情報。
APIを使用する準備
ここ掲載しているテストには以下の準備が必要。
- Google Colabの用意
- OANDA デモ口座の用意
- アクセストークンの発行とアカウントIDの確認
- OANDAへのAPI接続
Google Colab
まずは、Google Colaboratory にアクセス。ログインしている場合は以下の画面が表示される。
「PYTHON3の新しいノートブック」(画像の赤枠部分)をクリックすると、空白のノートブックを開くことができる。これだけでPythonのテストを行うことができる。サーバーを用意して環境を構築する必要がない。
OANDA デモ口座
OANDA デモ口座ページ(Google検索)にアクセス。
申し込みから数分でデモ環境を利用することができるようになる。
アクセストークンの発行とアカウントIDを確認
デモ口座では、仮想で300万円入金された本番と同じ環境が用意されている。
- 「APIアクセスの管理」からアクセストークンを発行
- アカウントIDの確認
実際の口座でも同様の方法で確認できる。
OANDAへのAPI接続
まず、Googla Colabで以下を実行してoandapyV20
をインストールする。
!pip install oandapyV20
次に、APIへの接続(準備)を行う。
from oandapyV20 import API
accountID = "ここにアカウントIDを入力"
access_token = "ここにアクセストークンを入力"
api = API(access_token=access_token ,environment="practice")
※ 本番口座に接続する場合は,environment="practice"
は必要ない
価格ストリーミングの取得
import json
from oandapyV20.exceptions import V20Error
from oandapyV20.endpoints.pricing import PricingStream
instruments = "EUR_USD,EUR_JPY"
s = PricingStream(accountID=accountID, params={"instruments":instruments})
MAXREC = 10
try:
n = 0
for R in api.request(s):
print(json.dumps(R, indent=2))
n += 1
if n > MAXREC:
s.terminate("maxrecs received {}".format(MAXREC))
except V20Error as e:
print("Error: {}".format(e))
ヒストリカルデータの取得
import json
import pandas as pd
import oandapyV20.endpoints.instruments as instruments
from oandapyV20.types import DateTime
from datetime import datetime ,timedelta
from dateutil.relativedelta import relativedelta
def get_equity_df( since ,until ,interval ,price ) :
cnt = 'mid' if price=='M' else 'ask' if price=='A' else 'bid' if price=='B' else 'mid'
params = { "from": DateTime( since ).value
,"to": DateTime( until ).value
,"price": price
,"granularity": interval }
r = instruments.InstrumentsCandles( instrument="USD_JPY" ,params=params )
api.request( r )
raw_list = []
for raw in r.response['candles'] :
raw_list.append( [ raw['time'] ,raw[cnt]['o'] ,raw[cnt]['h'] ,raw[cnt]['l'] ,raw[cnt]['c'] ,raw['volume'] ] )
raw_df = pd.DataFrame( raw_list ,columns=[ 'Time' ,f'Open_{cnt}' ,f'High_{cnt}' ,f'Low_{cnt}' ,f'Close_{cnt}' ,'Volume' ] )
return raw_df
start = datetime.strptime( '2005-01-01' ,'%Y-%m-%d' )
end = datetime.strptime( '2019-12-31' ,'%Y-%m-%d' )
month = 12 * 2
interval = 'H4'
restart = 0
since = start + relativedelta( months=( restart ) )
until = start + relativedelta( months=( month + restart ) )
df = pd.DataFrame()
while True :
if until > datetime.now() :
until = datetime.now()
if relativedelta( since ,until ).months==0 : break
print( f'since:{ since } ,until:{ until }' )
raw_a = get_equity_df( since ,until ,interval ,'A' )
raw_b = get_equity_df( since ,until ,interval ,'B' )
raw = pd.merge( raw_a ,raw_b )
raw = raw.set_index( 'Time' )
raw.index = pd.to_datetime( raw.index )
df = pd.concat( [ df ,raw ] )
since = until
until = until + relativedelta( months=month )
if since >= end : break
取引に関するAPIの基本的な挙動
APIの挙動の備忘録。
- トランザクションのIDは全体で連番
- IDにはorderIDとtradeIDがある
- 同じ内容でも処理によって項目名が微妙に異なる
- エントリーの日時を表す項目が
orders.OrderCreate
の返り値ではtime
trades.tradeDetail
の返り値ではopenTime
- すべてのリクエストに対して
lastTransactionID
が必ず返される - 近すぎるSTOPは発注できない(未確認)
オーダーの操作
orders.OrderCreate( accountID ,data )
オーダーを作成するorders.OrdersPending( accountID ,orderID )
保留中のオーダー情報を取得するorders.OrderDetails( accountID ,orderID )
オーダーの詳細を取得するorders.OrderCancel( accountID ,orderID )
オーダーをキャンセルする
オーダーを作成する
エントリーのオーダーを作成する。オーダーには成行注文(Market Order)と指値注文(Limit Order)、逆指値注文(Stop Order)がある。
data
の中でtradeID
を指定することで決済の注文を、stopLossOnFill
とtakeProfitOnFill
を指定することでOCO注文を作成することもできる。
MARKET ORDER(成行注文でエントリー)
import oandapyV20.endpoints.orders as orders
order_data = {
"order": {
"instrument": "USD_JPY",
"units": "+100",
"type": "MARKET",
}
}
o = orders.OrderCreate(accountID, data=order_data)
api.request( o )
o.response
「買いか売りか」は"units":"+100"
で取引量と共に表現する。1000通貨の売りなら"-1000"
と指定する。
作成した注文はorderCreateTransaction
、実行された取引(trade)はorderFillTransaction
として返ってくる。この場合、成行注文のorderID
は139であり、tradeID
は140。
{'lastTransactionID': '140',
'orderCreateTransaction': {'accountID': '<accountID>',
'batchID': '139',
'id': '139',
'instrument': 'USD_JPY',
'positionFill': 'DEFAULT',
'reason': 'CLIENT_ORDER',
'requestID': '60632676041088500',
'time': '2019-10-14T12:03:00.543969658Z',
'timeInForce': 'FOK',
'type': 'MARKET_ORDER',
'units': '100',
'userID': <userID>},
'orderFillTransaction': {'accountBalance': '3003167.2000',
'accountID': '<accountID>',
'batchID': '139',
'commission': '0.0000',
'financing': '0.0000',
'fullPrice': {'asks': [{'liquidity': '250000', 'price': '108.246'}],
'bids': [{'liquidity': '250000', 'price': '108.242'}],
'closeoutAsk': '108.265',
'closeoutBid': '108.223',
'timestamp': '2019-10-14T12:02:58.891477244Z'},
'fullVWAP': '108.246',
'gainQuoteHomeConversionFactor': '1',
'guaranteedExecutionFee': '0.0000',
'halfSpreadCost': '0.2000',
'id': '140',
'instrument': 'USD_JPY',
'lossQuoteHomeConversionFactor': '1',
'orderID': '139',
'pl': '0.0000',
'price': '108.246',
'reason': 'MARKET_ORDER',
'requestID': '60632676041088500',
'requestedUnits': '100',
'time': '2019-10-14T12:03:00.543969658Z',
'tradeOpened': {'guaranteedExecutionFee': '0.0000',
'halfSpreadCost': '0.2000',
'initialMarginRequired': '432.9760',
'price': '108.246',
'tradeID': '140',
'units': '100'},
'type': 'ORDER_FILL',
'units': '100',
'userID': <userID>},
'relatedTransactionIDs': ['139', '140']}
STOP ORDER(逆指値注文でエントリー)
import oandapyV20.endpoints.orders as orders
order_data = {
"order": {
"price": "107.765"
,"instrument": "USD_JPY"
,"units": "+10000"
,"type": "STOP"
}
}
o = orders.OrderCreate(accountID, data=order_data)
api.request( o )
o.response
指値注文や逆指値注文ですぐに取引が完了しなかった場合はorderFillTransaction
が返ってこない。エントリーされたことを確認するにはorderDetail
で確認するしかない。
{'lastTransactionID': '18',
'orderCreateTransaction': {'accountID': '<accountID>',
'batchID': '18',
'id': '18',
'instrument': 'USD_JPY',
'partialFill': 'DEFAULT',
'positionFill': 'DEFAULT',
'price': '107.000',
'reason': 'CLIENT_ORDER',
'requestID': '42615646265393854',
'time': '2019-10-07T05:47:18.751402370Z',
'timeInForce': 'GTC',
'triggerCondition': 'DEFAULT',
'type': 'STOP_ORDER',
'units': '10000',
'userID': <userID>},
'relatedTransactionIDs': ['18']}
保留中のオーダー情報を取得する
未約定のオーダーをリスト(配列)で取得することができる。オーダーはエントリーとイグジットどちらも含まれる。
import oandapyV20.endpoints.orders as orders
c = orders.OrdersPending( accountID )
api.request( c )
c.response
{'lastTransactionID': '16',
'orders': [{'createTime': '2019-10-07T05:39:33.418717612Z',
'id': '16',
'instrument': 'USD_JPY',
'partialFill': 'DEFAULT_FILL',
'positionFill': 'DEFAULT',
'price': '107.000',
'state': 'PENDING',
'timeInForce': 'GTC',
'triggerCondition': 'DEFAULT',
'type': 'STOP',
'units': '10000'}]}
オーダーの詳細を取得する
import oandapyV20.endpoints.orders as orders
c = orders.OrderDetails( accountID ,orderID='133' )
api.request( c )
c.response
オーダーの詳細は、エントリーやイグジット、注文の状態と種類など多岐に渡る。返り値を何パターンか記録しておく。
# キャンセルしたエントリーの注文に対する戻り値
{'lastTransactionID': '19',
'order': {'cancelledTime': '2019-10-07T05:47:41.114658220Z',
'cancellingTransactionID': '19',
'createTime': '2019-10-07T05:47:18.751402370Z',
'id': '18',
'instrument': 'USD_JPY',
'partialFill': 'DEFAULT_FILL',
'positionFill': 'DEFAULT',
'price': '107.000',
'state': 'CANCELLED',
'timeInForce': 'GTC',
'triggerCondition': 'DEFAULT',
'type': 'STOP',
'units': '10000'}}
# 執行済みのエントリー注文に対する戻り値
{'lastTransactionID': '134',
'order': {'createTime': '2019-10-10T13:49:55.429422636Z',
'filledTime': '2019-10-10T13:49:55.429422636Z',
'fillingTransactionID': '134',
'id': '133',
'instrument': 'USD_JPY',
'partialFill': 'DEFAULT_FILL',
'positionFill': 'DEFAULT',
'price': '107.765',
'state': 'FILLED',
'timeInForce': 'GTC',
'tradeOpenedID': '134',
'triggerCondition': 'DEFAULT',
'type': 'STOP',
'units': '10000'}}
# 決済の注文に対する戻り値
{'lastTransactionID': '23',
'order': {'createTime': '2019-10-07T05:51:17.637841229Z',
'guaranteed': False,
'id': '23',
'price': '106.870',
'state': 'PENDING',
'timeInForce': 'GTC',
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'STOP_LOSS'}}
# 執行済みの決済注文に対する戻り値
{'lastTransactionID': '28',
'order': {'createTime': '2019-10-07T05:56:45.327517046Z',
'filledTime': '2019-10-07T05:56:45.810216477Z',
'fillingTransactionID': '27',
'id': '24',
'price': '106.890',
'state': 'FILLED',
'timeInForce': 'GTC',
'tradeClosedIDs': ['21'],
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'TAKE_PROFIT'}}
オーダーをキャンセルする
指定するIDがtradeID
だとエラーが返ってくる。
import oandapyV20.endpoints.orders as orders
c = orders.OrderCancel( accountID ,orderID='18' )
api.request( c )
c.response
{'lastTransactionID': '19',
'orderCancelTransaction': {'accountID': '<accountID>',
'batchID': '19',
'id': '19',
'orderID': '18',
'reason': 'CLIENT_REQUEST',
'requestID': '42615646361899207',
'time': '2019-10-07T05:47:41.114658220Z',
'type': 'ORDER_CANCEL',
'userID': <userID>},
'relatedTransactionIDs': ['19']}
ポジションの操作
positions.PositionClose( acccountID )
ポジションを決済するpositions.PositionDetails( accountID )
ポジションの詳細を取得する
ポジションを決済する
"longUnits":"1000"
で取引量を指定して決済、"longUnits":"ALL"
ですべてのポジションを決済する。ポジションが存在しない場合はエラーが返ってくる。
import oandapyV20.endpoints.positions as positions
position_data = { "longUnits": "ALL" }
p = positions.PositionClose( accountID=accountID, data=position_data, instrument="USD_JPY" )
api.request( p )
p.response
{'lastTransactionID': '48',
'longOrderCreateTransaction': {'accountID': '<accountID>',
'batchID': '47',
'id': '47',
'instrument': 'USD_JPY',
'longPositionCloseout': {'instrument': 'USD_JPY', 'units': 'ALL'},
'positionFill': 'REDUCE_ONLY',
'reason': 'POSITION_CLOSEOUT',
'requestID': '60630740234934498',
'time': '2019-10-09T03:50:48.377768343Z',
'timeInForce': 'FOK',
'type': 'MARKET_ORDER',
'units': '-11000',
'userID': <userID>},
'longOrderFillTransaction': {'accountBalance': '3002262.4000',
'accountID': '<accountID>',
'batchID': '47',
'commission': '0.0000',
'financing': '0.0000',
'fullPrice': {'asks': [{'liquidity': '250000', 'price': '107.162'}],
'bids': [{'liquidity': '250000', 'price': '107.158'}],
'closeoutAsk': '107.181',
'closeoutBid': '107.139',
'timestamp': '2019-10-09T03:48:05.569135841Z'},
'fullVWAP': '107.158',
'gainQuoteHomeConversionFactor': '1',
'guaranteedExecutionFee': '0.0000',
'halfSpreadCost': '22.0000',
'id': '48',
'instrument': 'USD_JPY',
'lossQuoteHomeConversionFactor': '1',
'orderID': '47',
'pl': '1896.0000',
'price': '107.158',
'reason': 'MARKET_ORDER_POSITION_CLOSEOUT',
'requestID': '60630740234934498',
'requestedUnits': '-11000',
'time': '2019-10-09T03:50:48.377768343Z',
'tradesClosed': [{'financing': '0.0000',
'guaranteedExecutionFee': '0.0000',
'halfSpreadCost': '20.0000',
'price': '107.158',
'realizedPL': '1820.0000',
'tradeID': '36',
'units': '-10000'},
{'financing': '0.0000',
'guaranteedExecutionFee': '0.0000',
'halfSpreadCost': '2.0000',
'price': '107.158',
'realizedPL': '76.0000',
'tradeID': '40',
'units': '-1000'}],
'type': 'ORDER_FILL',
'units': '-11000',
'userID': <userID>},
'relatedTransactionIDs': ['47', '48']}
ポジションの詳細を取得する
import oandapyV20.endpoints.positions as positions
p = positions.PositionDetails(accountID=accountID, instrument="USD_JPY")
api.request( p )
p.response
{'lastTransactionID': '138',
'trade': {'averageClosePrice': '106.890',
'closeTime': '2019-10-07T05:56:45.810216477Z',
'closingTransactionIDs': ['27'],
'currentUnits': '0',
'dividend': '0.0000',
'financing': '0.0000',
'id': '21',
'initialMarginRequired': '42744.0000',
'initialUnits': '10000',
'instrument': 'USD_JPY',
'openTime': '2019-10-07T05:48:02.507227911Z',
'price': '106.862',
'realizedPL': '280.0000',
'state': 'CLOSED',
'stopLossOrder': {'cancelledTime': '2019-10-07T05:56:45.810216477Z',
'cancellingTransactionID': '28',
'createTime': '2019-10-07T05:56:45.327517046Z',
'guaranteed': False,
'id': '26',
'price': '106.870',
'replacesOrderID': '23',
'state': 'CANCELLED',
'timeInForce': 'GTC',
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'STOP_LOSS'},
'takeProfitOrder': {'createTime': '2019-10-07T05:56:45.327517046Z',
'filledTime': '2019-10-07T05:56:45.810216477Z',
'fillingTransactionID': '27',
'id': '24',
'price': '106.890',
'state': 'FILLED',
'timeInForce': 'GTC',
'tradeClosedIDs': ['21'],
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'TAKE_PROFIT'}}}
取引系の操作
trades.TradeDetails( accountID ,tradeID )
トレードの詳細を取得するtrades.TradeClose( accountID ,tradeID ,data )
トレードの決済trades.TradeCRCDO( accountID ,tradeID ,data )
トレードに関連する注文を行う
PositionClose
は、tradeID
の垣根を超えた決済を行えるイメージ。勝手に調整してくれる。対してTradeClose
は、tradeID
に紐付いた決済。
トレードの詳細を取得する
import oandapyV20.endpoints.trades as trades
r = trades.TradeDetails( accountID ,tradeID='21' )
api.request( r )
r.response
{'lastTransactionID': '138',
'trade': {'averageClosePrice': '106.890',
'closeTime': '2019-10-07T05:56:45.810216477Z',
'closingTransactionIDs': ['27'],
'currentUnits': '0',
'dividend': '0.0000',
'financing': '0.0000',
'id': '21',
'initialMarginRequired': '42744.0000',
'initialUnits': '10000',
'instrument': 'USD_JPY',
'openTime': '2019-10-07T05:48:02.507227911Z',
'price': '106.862',
'realizedPL': '280.0000',
'state': 'CLOSED',
'stopLossOrder': {'cancelledTime': '2019-10-07T05:56:45.810216477Z',
'cancellingTransactionID': '28',
'createTime': '2019-10-07T05:56:45.327517046Z',
'guaranteed': False,
'id': '26',
'price': '106.870',
'replacesOrderID': '23',
'state': 'CANCELLED',
'timeInForce': 'GTC',
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'STOP_LOSS'},
'takeProfitOrder': {'createTime': '2019-10-07T05:56:45.327517046Z',
'filledTime': '2019-10-07T05:56:45.810216477Z',
'fillingTransactionID': '27',
'id': '24',
'price': '106.890',
'state': 'FILLED',
'timeInForce': 'GTC',
'tradeClosedIDs': ['21'],
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'TAKE_PROFIT'}}}
トレードの決済
成行注文で決済する。data={"units":"10"}
などとして取引量を調整することも可能。
import oandapyV20.endpoints.trades as trades
r = trades.TradeClose( accountID ,tradeID='13' )
api.request( r )
r.response
{'lastTransactionID': '15',
'orderCreateTransaction': {'accountID': '<accountID>',
'batchID': '14',
'id': '14',
'instrument': 'USD_JPY',
'positionFill': 'REDUCE_ONLY',
'reason': 'TRADE_CLOSE',
'requestID': '42615643621954763',
'time': '2019-10-07T05:36:47.993201609Z',
'timeInForce': 'FOK',
'tradeClose': {'tradeID': '13', 'units': 'ALL'},
'type': 'MARKET_ORDER',
'units': '-10000',
'userID': <userID>},
'orderFillTransaction': {'accountBalance': '2999890.0000',
'accountID': '<accountID>',
'batchID': '14',
'commission': '0.0000',
'financing': '0.0000',
'fullPrice': {'asks': [{'liquidity': '250000', 'price': '106.855'}],
'bids': [{'liquidity': '250000', 'price': '106.851'}],
'closeoutAsk': '106.874',
'closeoutBid': '106.832',
'timestamp': '2019-10-07T05:36:31.723734747Z'},
'fullVWAP': '106.851',
'gainQuoteHomeConversionFactor': '1',
'guaranteedExecutionFee': '0.0000',
'halfSpreadCost': '20.0000',
'id': '15',
'instrument': 'USD_JPY',
'lossQuoteHomeConversionFactor': '1',
'orderID': '14',
'pl': '-110.0000',
'price': '106.851',
'reason': 'MARKET_ORDER_TRADE_CLOSE',
'requestID': '42615643621954763',
'requestedUnits': '-10000',
'time': '2019-10-07T05:36:47.993201609Z',
'tradesClosed': [{'financing': '0.0000',
'guaranteedExecutionFee': '0.0000',
'halfSpreadCost': '20.0000',
'price': '106.851',
'realizedPL': '-110.0000',
'tradeID': '13',
'units': '-10000'}],
'type': 'ORDER_FILL',
'units': '-10000',
'userID': <userID>},
'relatedTransactionIDs': ['14', '15']}
トレードに関連する注文を行う
利確、損切り、トレーリングストップなどの注文を行うことができる。
import oandapyV20.endpoints.trades as trades
r = trades.TradeCRCDO( accountID ,tradeID='21' ,data={
'stopLoss': {
'timeInForce': 'GTC'
,'price': '106.870'
}
,'takeProfit': {
'timeInForce': 'GTC'
,'price': '106.89'
}
} )
api.request( r )
r.response
{'lastTransactionID': '26',
'relatedTransactionIDs': ['24', '25', '26'],
'stopLossOrderCancelTransaction': {'accountID': '<accountID>',
'batchID': '24',
'id': '25',
'orderID': '23',
'reason': 'CLIENT_REQUEST_REPLACED',
'replacedByOrderID': '26',
'requestID': '78644445666300450',
'time': '2019-10-07T05:56:45.327517046Z',
'type': 'ORDER_CANCEL',
'userID': <userID>},
'stopLossOrderTransaction': {'accountID': '<accountID>',
'batchID': '24',
'cancellingTransactionID': '25',
'guaranteed': False,
'id': '26',
'price': '106.870',
'reason': 'REPLACEMENT',
'replacesOrderID': '23',
'requestID': '78644445666300450',
'time': '2019-10-07T05:56:45.327517046Z',
'timeInForce': 'GTC',
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'STOP_LOSS_ORDER',
'userID': <userID>},
'takeProfitOrderTransaction': {'accountID': '<accountID>',
'batchID': '24',
'id': '24',
'price': '106.890',
'reason': 'CLIENT_ORDER',
'requestID': '78644445666300450',
'time': '2019-10-07T05:56:45.327517046Z',
'timeInForce': 'GTC',
'tradeID': '21',
'triggerCondition': 'DEFAULT',
'type': 'TAKE_PROFIT_ORDER',
'userID': <userID>}}
取引系の操作
accounts.AccountSummary( accountID )
アカウントの残高などを取得する
アカウントの残高などを取得する
import oandapyV20.endpoints.accounts as accounts
r = accounts.AccountSummary( accountID )
api.request( r )
r.response
{'account': {'NAV': '3000130.0000',
'alias': 'Primary',
'balance': '3000170.0000',
'commission': '0.0000',
'createdByUserID': <userID>,
'createdTime': '2019-09-18T14:15:24.150417961Z',
'currency': 'JPY',
'dividend': '0',
'financing': '0.0000',
'guaranteedExecutionFees': '0.0000',
'guaranteedStopLossOrderMode': 'DISABLED',
'hedgingEnabled': False,
'id': '<accountID>',
'lastTransactionID': '30',
'marginAvailable': '2957341.2000',
'marginCloseoutMarginUsed': '42788.8000',
'marginCloseoutNAV': '3000150.0000',
'marginCloseoutPercent': '0.01426',
'marginCloseoutPositionValue': '1069720.0000',
'marginCloseoutUnrealizedPL': '-20.0000',
'marginRate': '0.04',
'marginUsed': '42788.8000',
'openPositionCount': 1,
'openTradeCount': 1,
'pendingOrderCount': 0,
'pl': '170.0000',
'positionValue': '1069720.0000',
'resettablePL': '170.0000',
'resettablePLTime': '0',
'unrealizedPL': '-40.0000',
'withdrawalLimit': '2957341.2000'},
'lastTransactionID': '30'}
- どんな記事?
- Pythonにしかできないこと
- 参考
- APIを使用する準備
- 価格ストリーミングの取得
- ヒストリカルデータの取得
- 取引に関するAPIの基本的な挙動
- オーダーの操作
- ポジションの操作
- 取引系の操作
- 取引系の操作
- 記事をシェア