یہ کچھ عرصہ ہو گیا ہے جب سے ہم نے ایونٹ سے چلنے والے بیک ٹیسٹر پر غور کیا ہے ، جس پر ہم نے اس مضمون میں تبادلہ خیال کرنا شروع کیا۔ حصہ VI میں میں نے ایک اسٹینڈ ان ایگزیکشن ہینڈلر ماڈل کوڈ کرنے کا طریقہ بیان کیا ہے جو تاریخی بیک ٹسٹنگ کی صورتحال کے لئے کام کرتا ہے۔ اس مضمون میں ہم براہ راست تجارتی نظام کی طرف منتقل ہونے کے لئے متعلقہ انٹرایکٹو بروکرز API ہینڈلر کوڈ کرنے جارہے ہیں۔
میں نے پہلے ہی تبادلہ خیال کیا ہے کہ ٹریڈر ورک سٹیشن کو ڈاؤن لوڈ کرنے اور انٹرایکٹو بروکرز ڈیمو اکاؤنٹ بنانے کے ساتھ ساتھ IbPy کا استعمال کرتے ہوئے IB API کے لئے بنیادی انٹرفیس بنانے کا طریقہ۔ یہ مضمون بنیادی IbPy انٹرفیس کو ایونٹ سے چلنے والے نظام میں لپیٹ دے گا ، تاکہ جب یہ براہ راست مارکیٹ فیڈ کے ساتھ جوڑا جائے تو ، یہ خودکار عمل درآمد کے نظام کی بنیاد تشکیل دے گا۔
IBExecutionHandler کلاس کا بنیادی خیال (نیچے ملاحظہ کریں) ایونٹ کی قطار سے آرڈر ایونٹ کی مثالیں وصول کرنا ہے اور پھر ان کو براہ راست انٹرایکٹو بروکرز آرڈر API کے خلاف IbPy لائبریری کا استعمال کرتے ہوئے انجام دینا ہے۔ کلاس API کے ذریعہ واپس بھیجے گئے
کلاس خود ممکنہ طور پر عملدرآمد کی اصلاح کی منطق کے ساتھ ساتھ نفیس غلطی ہینڈلنگ کے ساتھ کافی پیچیدہ بن سکتی ہے۔ تاہم ، میں نے اسے نسبتا simple آسان رکھنے کا انتخاب کیا ہے تاکہ آپ اہم خیالات کو دیکھ سکیں اور اسے اپنی مخصوص تجارتی طرز کے مطابق سمت میں بڑھا سکیں۔
ہمیشہ کی طرح ، پہلا کام پائتھون فائل بنانا اور ضروری لائبریریاں درآمد کرنا ہے۔ فائل کو ib_execution.py کہا جاتا ہے اور وہ دوسری ایونٹ سے چلنے والی فائلوں کی طرح اسی ڈائرکٹری میں رہتی ہے۔
ہم ضروری تاریخ / وقت ہینڈلنگ لائبریریوں، IbPy اشیاء اور مخصوص واقعہ اشیاء IBExecutionHandler کی طرف سے سنبھالا جاتا ہے کہ درآمد:
# ib_execution.py
import datetime
import time
from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.opt import ibConnection, message
from event import FillEvent, OrderEvent
from execution import ExecutionHandler
اب ہم IBExecutionHandler کلاس کی وضاحت.شروع کریںکنسٹرکٹر سب سے پہلے واقعات کی قطار کے علم کی ضرورت ہوتی ہے۔ اس میں آرڈر_روٹنگ کی وضاحت کی بھی ضرورت ہوتی ہے ، جسے میں نے
اس طریقہ کار کے اندر ہم ایک fill_dict لغت بناتے ہیں ، جو بعد میں FillEvent مثالوں کی تخلیق میں استعمال کے لئے ضروری ہے۔ ہم اپنے کنکشن کی معلومات کو انٹرایکٹو بروکرز API میں اسٹور کرنے کے لئے tws_conn کنکشن آبجیکٹ بھی بناتے ہیں۔ ہمیں ایک ابتدائی ڈیفالٹ آرڈر_آئی ڈی بھی بنانا ہوتا ہے ، جو نقل و حرکت سے بچنے کے لئے تمام بعد کے احکامات کا سراغ لگاتا ہے۔ آخر میں ہم میسج ہینڈلرز کو رجسٹر کرتے ہیں (جس کی وضاحت ہم ذیل میں مزید تفصیل سے کریں گے):
# ib_execution.py
class IBExecutionHandler(ExecutionHandler):
"""
Handles order execution via the Interactive Brokers
API, for use against accounts when trading live
directly.
"""
def __init__(self, events,
order_routing="SMART",
currency="USD"):
"""
Initialises the IBExecutionHandler instance.
"""
self.events = events
self.order_routing = order_routing
self.currency = currency
self.fill_dict = {}
self.tws_conn = self.create_tws_connection()
self.order_id = self.create_initial_order_id()
self.register_handlers()
آئی بی API ایک پیغام پر مبنی واقعہ کا نظام استعمال کرتا ہے جو ہماری کلاس کو مخصوص پیغامات کا جواب دینے کی اجازت دیتا ہے ، جس طرح ایونٹ سے چلنے والے بیک ٹیسٹر کے ساتھ ہی ہوتا ہے۔ میں نے _error_handler طریقہ کے ذریعہ ٹرمینل میں آؤٹ پٹ کے علاوہ ، کوئی حقیقی غلطی ہینڈلنگ (مختصر مقاصد کے لئے) شامل نہیں کی ہے۔
دوسری طرف ، _reply_handler طریقہ کار کا استعمال اس بات کا تعین کرنے کے لئے کیا جاتا ہے کہ آیا FillEvent مثال بنانے کی ضرورت ہے۔ طریقہ کار پوچھتا ہے کہ آیا
اگر یہ ایک
# ib_execution.py
def _error_handler(self, msg):
"""
Handles the capturing of error messages
"""
# Currently no error handling.
print "Server Error: %s" % msg
def _reply_handler(self, msg):
"""
Handles of server replies
"""
# Handle open order orderId processing
if msg.typeName == "openOrder" and \
msg.orderId == self.order_id and \
not self.fill_dict.has_key(msg.orderId):
self.create_fill_dict_entry(msg)
# Handle Fills
if msg.typeName == "orderStatus" and \
msg.status == "Filled" and \
self.fill_dict[msg.orderId]["filled"] == False:
self.create_fill(msg)
print "Server Response: %s, %s\n" % (msg.typeName, msg)
مندرجہ ذیل طریقہ ، create_tws_connection ، IbPy ibConnection آبجیکٹ کا استعمال کرتے ہوئے IB API سے رابطہ قائم کرتا ہے۔ یہ 7496 کی ڈیفالٹ پورٹ اور 10 کی ڈیفالٹ کلائنٹ ID کا استعمال کرتا ہے۔ ایک بار جب آبجیکٹ بن جاتا ہے تو ، رابطہ قائم کرنے کا طریقہ رابطہ قائم کرنے کے لئے کہا جاتا ہے:
# ib_execution.py
def create_tws_connection(self):
"""
Connect to the Trader Workstation (TWS) running on the
usual port of 7496, with a clientId of 10.
The clientId is chosen by us and we will need
separate IDs for both the execution connection and
market data connection, if the latter is used elsewhere.
"""
tws_conn = ibConnection()
tws_conn.connect()
return tws_conn
علیحدہ احکامات کا سراغ لگانے کے لئے (تعاقب بھرنے کے مقاصد کے لئے) مندرجہ ذیل طریقہ create_initial_order_id استعمال کیا جاتا ہے۔ میں نے اسے
# ib_execution.py
def create_initial_order_id(self):
"""
Creates the initial order ID used for Interactive
Brokers to keep track of submitted orders.
"""
# There is scope for more logic here, but we
# will use "1" as the default for now.
return 1
مندرجہ ذیل طریقہ، register_handlers، صرف TWS کنکشن کے ساتھ غلطی اور جواب ہینڈلر طریقوں کو اوپر بیان کیا رجسٹر کرتا ہے:
# ib_execution.py
def register_handlers(self):
"""
Register the error and server reply
message handling functions.
"""
# Assign the error handling function defined above
# to the TWS connection
self.tws_conn.register(self._error_handler, 'Error')
# Assign all of the server reply messages to the
# reply_handler function defined above
self.tws_conn.registerAll(self._reply_handler)
آئی بی پی کا استعمال کرنے کے بارے میں پچھلے ٹیوٹوریل کی طرح ہمیں بھی معاہدہ کی مثال بنانے کی ضرورت ہے اور پھر اسے آرڈر کی مثال کے ساتھ جوڑنا ہے ، جو آئی بی اے پی آئی کو بھیجا جائے گا۔ مندرجہ ذیل طریقہ ، تخلیق_ معاہدہ ، اس جوڑے کا پہلا جزو تیار کرتا ہے۔ اس سے ٹکر علامت ، سیکیورٹی کی قسم (جیسے اسٹاک یا مستقبل) ، تبادلہ / بنیادی تبادلہ اور کرنسی کی توقع ہوتی ہے۔ یہ معاہدہ کی مثال واپس کرتا ہے:
# ib_execution.py
def create_contract(self, symbol, sec_type, exch, prim_exch, curr):
"""
Create a Contract object defining what will
be purchased, at which exchange and in which currency.
symbol - The ticker symbol for the contract
sec_type - The security type for the contract ('STK' is 'stock')
exch - The exchange to carry out the contract on
prim_exch - The primary exchange to carry out the contract on
curr - The currency in which to purchase the contract
"""
contract = Contract()
contract.m_symbol = symbol
contract.m_secType = sec_type
contract.m_exchange = exch
contract.m_primaryExch = prim_exch
contract.m_currency = curr
return contract
مندرجہ ذیل طریقہ ، create_order ، جوڑی کا دوسرا جزو ، یعنی آرڈر کی مثال تیار کرتا ہے۔ یہ آرڈر کی قسم (جیسے مارکیٹ یا حد) ، تجارت کرنے کے لئے اثاثہ کی مقدار اور
# ib_execution.py
def create_order(self, order_type, quantity, action):
"""
Create an Order object (Market/Limit) to go long/short.
order_type - 'MKT', 'LMT' for Market or Limit orders
quantity - Integral number of assets to order
action - 'BUY' or 'SELL'
"""
order = Order()
order.m_orderType = order_type
order.m_totalQuantity = quantity
order.m_action = action
return order
کسی خاص آرڈر آئی ڈی کے لئے فل ایونٹ مثالوں کی نقل و حرکت سے بچنے کے ل we ، ہم کسی خاص آرڈر آئی ڈی سے ملنے والی چابیاں ذخیرہ کرنے کے لئے فل_ڈکٹ نامی لغت کا استعمال کرتے ہیں۔ جب فل پیدا ہوجاتا ہے تو کسی خاص آرڈر آئی ڈی کے لئے کسی اندراج کی
# ib_execution.py
def create_fill_dict_entry(self, msg):
"""
Creates an entry in the Fill Dictionary that lists
orderIds and provides security information. This is
needed for the event-driven behaviour of the IB
server message behaviour.
"""
self.fill_dict[msg.orderId] = {
"symbol": msg.contract.m_symbol,
"exchange": msg.contract.m_exchange,
"direction": msg.order.m_action,
"filled": False
}
مندرجہ ذیل طریقہ، create_fill، اصل میں FillEvent مثال تخلیق کرتا ہے اور اسے واقعات کی قطار میں رکھتا ہے:
# ib_execution.py
def create_fill(self, msg):
"""
Handles the creation of the FillEvent that will be
placed onto the events queue subsequent to an order
being filled.
"""
fd = self.fill_dict[msg.orderId]
# Prepare the fill data
symbol = fd["symbol"]
exchange = fd["exchange"]
filled = msg.filled
direction = fd["direction"]
fill_cost = msg.avgFillPrice
# Create a fill event object
fill = FillEvent(
datetime.datetime.utcnow(), symbol,
exchange, filled, direction, fill_cost
)
# Make sure that multiple messages don't create
# additional fills.
self.fill_dict[msg.orderId]["filled"] = True
# Place the fill event onto the event queue
self.events.put(fill_event)
اب جب کہ مذکورہ بالا تمام طریقوں کو نافذ کیا گیا ہے ، اب بھی ExecutionHandler تجریدی بیس کلاس سے execute_order طریقہ کو کالعدم کرنا باقی ہے۔ یہ طریقہ اصل میں IB API کے ساتھ آرڈر کی جگہ لے لیتا ہے۔
ہم سب سے پہلے چیک کرتے ہیں کہ اس طریقہ کار کو موصول ہونے والا واقعہ واقعی آرڈر ایونٹ ہے اور پھر معاہدہ اور آرڈر اشیاء کو ان کے متعلقہ پیرامیٹرز کے ساتھ تیار کرتے ہیں۔ ایک بار جب دونوں بنائے جاتے ہیں تو ، کنکشن آبجیکٹ کا IbPy طریقہ placeOrder اس سے وابستہ order_id کے ساتھ بلایا جاتا ہے۔
یہ یقینی بنانے کے لئے کہ آرڈر واقعی آئی بی تک جاتا ہے اس وقت.sleep(1) طریقہ کار کو فون کرنا انتہائی ضروری ہے۔ اس لائن کو ہٹانے سے ای پی آئی کا inconsistent رویہ پیدا ہوتا ہے ، کم از کم میرے سسٹم پر!
آخر میں، ہم آرڈر آئی ڈی میں اضافہ کرتے ہیں تاکہ ہم اس بات کو یقینی بنائیں کہ ہم آرڈر کی نقل نہ کریں:
# ib_execution.py
def execute_order(self, event):
"""
Creates the necessary InteractiveBrokers order object
and submits it to IB via their API.
The results are then queried in order to generate a
corresponding Fill object, which is placed back on
the event queue.
Parameters:
event - Contains an Event object with order information.
"""
if event.type == 'ORDER':
# Prepare the parameters for the asset order
asset = event.symbol
asset_type = "STK"
order_type = event.order_type
quantity = event.quantity
direction = event.direction
# Create the Interactive Brokers contract via the
# passed Order event
ib_contract = self.create_contract(
asset, asset_type, self.order_routing,
self.order_routing, self.currency
)
# Create the Interactive Brokers order via the
# passed Order event
ib_order = self.create_order(
order_type, quantity, direction
)
# Use the connection to the send the order to IB
self.tws_conn.placeOrder(
self.order_id, ib_contract, ib_order
)
# NOTE: This following line is crucial.
# It ensures the order goes through!
time.sleep(1)
# Increment the order ID for this session
self.order_id += 1
یہ کلاس ایک انٹرایکٹو بروکرز ایگزیکشن ہینڈلر کی بنیاد بناتی ہے اور اسے نقلی ایگزیکشن ہینڈلر کی جگہ استعمال کیا جاسکتا ہے ، جو صرف بیک ٹیسٹنگ کے لئے موزوں ہے۔ تاہم ، آئی بی ہینڈلر کو استعمال کرنے سے پہلے ، بیک ٹیسٹر سسٹم کے تاریخی ڈیٹا فیڈ ہینڈلر کی جگہ لینا ایک رواں مارکیٹ فیڈ ہینڈلر بنانا ضروری ہے۔ یہ مستقبل کے مضمون کا موضوع ہوگا۔
اس طرح ہم بیک ٹیسٹ اور لائیو سسٹم سے زیادہ سے زیادہ دوبارہ استعمال کر رہے ہیں تاکہ یہ یقینی بنایا جا سکے کہ کوڈ