You are on page 1of 47

QTPyLib Documentation

Release latest

Ran Aroussi

August 25, 2016


Contents

1 Features 3

2 Quickstart 5

3 Installation 9

4 Legal Stuff 11

i
ii
QTPyLib Documentation, Release latest

QTPyLib (Quantitative Trading Python Library) is a simple, event-driven algorithmic trading system written in Python
3, that supports backtesting and live trading using Interactive Brokers for market data and order execution.
I originally developed QTPyLib because I wanted for a simple (but powerful) trading library that will let me to focus
on the trading logic itself and ignore everything else.
Full Documentation »

Contents 1
QTPyLib Documentation, Release latest

2 Contents
CHAPTER 1

Features

• A continuously-running Blotter that lets you capture market data even when your algos aren’t running.
• Tick, Bar and Trade data is stored in MySQL for later analisys and backtesting.
• Using pub/sub architecture using ØMQ (ZeroMQ) for communicating between the Algo and the Blotter allows
for a single Blotter/multiple Algos running on the same machine.
• Includes many common indicators that you can seamlessly use in your algorithm.
• Ability to import any Python library (such as scikit-learn or TA-Lib) to use them in your algorithms.
• Have orders delivered to your mobile via SMS (requires a Nexmo or Twilio account)

3
QTPyLib Documentation, Release latest

4 Chapter 1. Features
CHAPTER 2

Quickstart

There are 5 main components to QTPyLib:


1. Blotter - handles market data retreival and processing.
2. Broker - sends and proccess orders/positions (abstracted layer).
3. Algo - (sub-class of Broker) communicates with the Blotter to pass market data to your strategies, and
proccess/positions orders via Broker.
4. Reports - provides real time monitoring of trades and open opsitions via Web App, as well as a simple REST
API for trades, open positions and market data.
5. Lastly, Your Strategies, which are sub-classes of Algo, handle the trading logic/rules. This is where you’ll
write most of your code.

2.1 1. Get Market Data

To get started, you need to first create a Blotter script:


# blotter.py
from qtpylib.blotter import Blotter

class MainBlotter(Blotter):
pass # we just need the name

if __name__ == "__main__":
blotter = MainBlotter()
blotter.run()

Then, with IB TWS/GW running, run the Blotter from the command line:
$ python blotter.py

2.2 2. Write your Algorithm

While the Blotter running in the background, write and execute your algorithm:
# strategy.py
from qtpylib.algo import Algo

5
QTPyLib Documentation, Release latest

class CrossOver(Algo):

def on_start(self):
pass

def on_tick(self, instrument):


pass

def on_bar(self, instrument):


# get instrument history
bars = instrument.get_bars(window=100)

# or get all instruments history


# bars = self.bars[-20:]

# skip first 20 days to get full windows


if len(bars) < 20:
return

# compute averages using internal rolling_mean


bars['short_ma'] = bars['close'].rolling_mean(window=10)
bars['long_ma'] = bars['close'].rolling_mean(window=20)

# get current position data


positions = instrument.get_positions()

# trading logic - entry signal


if bars['short_ma'].crossed_above(bars['long_ma'])[-1]:
if not instrument.pending_orders and positions["position"] == 0:

# send a buy signal


self.signal("BUY", instrument, 1)

# record values for later analysis


self.record(ma_cross=1)

# trading logic - exit signal


elif bars['short_ma'].crossed_below(bars['long_ma'])[-1]:
if positions["position"] != 0:

# exit / flatten position


self.signal("EXIT", instrument)

# record values for later analysis


self.record(ma_cross=-1)

if __name__ == "__main__":
strategy = CrossOver(
instruments = [ ("ES", "FUT", "GLOBEX", "USD", 201609, 0.0, "") ], # ib tuples
resolution = "1T", # Pandas resolution (use "K" for tick bars)
tick_window = 20,
bar_window = 5,
preload = "1D",
timezone = "US/Central"
)
strategy.run()

6 Chapter 2. Quickstart
QTPyLib Documentation, Release latest

To run your algo in a live enviroment, from the command line, type:
$ python strategy.py --logpath ~/qtpy/

The resulting trades be saved in ~/qtpy/STRATEGY_YYYYMMDD.csv for later analysis.

2.3 3. Viewing Live Trades

While the Blotter running in the background, write the dashboard:


# dashboard.py
from qtpylib.reports import Reports

class Dahboard(Reports):
pass # we just need the name

if __name__ == "__main__":
dashboard = Dahboard(port = 5000)
dashboard.run()

To run your dashboard, run it from the command line:


$ python dashboard.py

>>> Dashboard password is: a0f36d95a9


>>> Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Now, point your browser to http://localhost:5000 and use the password generated to access your dashboard.

Note: Please refer to the Full Documentation to learn how to enable SMS notifications, use the bundled Indicators,
and more.

2.3. 3. Viewing Live Trades 7


QTPyLib Documentation, Release latest

8 Chapter 2. Quickstart
CHAPTER 3

Installation

First, install IbPy (for some reason I can’t get this installed automatically):
$ pip install git+git://github.com/blampe/IbPy --user

Then, install QTPyLib using pip:


$ pip install qtpylib --upgrade

3.1 Requirements

• Python >=3.4
• Pandas (tested to work with >=0.18.1)
• Numpy (tested to work with >=1.11.1)
• ØMQ (tested to with with >=15.2.1)
• PyMySQL (tested to with with >=0.7.6)
• pytz (tested to with with >=2016.6.1)
• dateutil (tested to with with >=2.5.1)
• Nexmo for SMS support (tested to with with >=1.2.0)
• Twilio for SMS support (tested to with with >=5.4.0)
• Flask for the Dashboard (tested to work with >=0.11)
• Requests (tested to with with >=2.10.0)
• Beautiful Soup (tested to work with >=4.3.2)
• IbPy (tested to work with >=0.7.2-9.00)
• ezIBpy (IbPy wrapper, tested to with with >=1.12.1)
• Latest Interactive Brokers’ TWS or IB Gateway installed and running on the machine

9
QTPyLib Documentation, Release latest

10 Chapter 3. Installation
CHAPTER 4

Legal Stuff

QTPyLib is distributed under the GNU Lesser General Public License v3.0. See the LICENSE.txt file in the release
for details. QTPyLib is not a product of Interactive Brokers, nor is it affiliated with Interactive Brokers.
You can find other examples in the qtpylib/examples directory.

4.1 P.S.

I’m very interested in your experience with QTPyLib. Please drop me an note with any feedback you have.
Ran Aroussi

4.2 Table of Contents

4.2.1 Installation

Install QTPyLib using pip

$ pip install qtpylib --upgrade

Note: QTPyLib requires IbPy, which, for some reason, cannot be bundled with the pip installer and requires manual
installation. To install IbPy manually, run:
$ pip install git+git://github.com/blampe/IbPy --user

Uninstall QTPyLib

To uninstall QTPyLib using pip, simply use:


$ pip uninstall qtpylib

11
QTPyLib Documentation, Release latest

Requirements

• Python >=3.4
• Pandas (tested to work with >=0.18.1)
• Numpy (tested to work with >=1.11.1)
• ØMQ (tested to with with >=15.2.1)
• PyMySQL (tested to with with >=0.7.6)
• pytz (tested to with with >=2016.6.1)
• dateutil (tested to with with >=2.5.1)
• Nexmo for SMS support (tested to with with >=1.2.0)
• Twilio for SMS support (tested to with with >=5.4.0)
• Flask for the Dashboard (tested to work with >=0.11)
• Requests (tested to with with >=2.10.0)
• Beautiful Soup (tested to work with >=4.3.2)
• IbPy (tested to work with >=0.7.2-9.00)
• ezIBpy (IbPy wrapper, tested to with with >=1.12.1)
• Latest Interactive Brokers’ TWS or IB Gateway installed and running on the machine

Install IB TWS / Gateway

In order for QTPyLib to be able to subscribe to market data and submit orders, you must have the latest version of
Interactive Brokers’ TWS or IB Gateway installed, running and properly configured on your machine.

Installation

Download TWS (offline version) or IB Gateway (requires less resources = recommended) from Interactive Brokers’
website, and follow the installation instructions.
• Download TWS (Traders Workstation)
• Download IB Gateway

Configure for API Access

After you install either TWS or IBGW, login using your account (or use edemo/demouser). The next thing to do is
to go to the menu, choose File, then choose Global Configuration.
Next, choose API on the left hand side, then go to Settings.
In the settings screen, make sure to set the options highlighted in the screenshot below:

12 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

Next, go to Precautions on the left side menu, and make sure *Bypass Order Precautions for API Orders is
checked.

4.2. Table of Contents 13


QTPyLib Documentation, Release latest

Now that your system is setup, it’s time to start programming your Algo...

4.2.2 Library Structure

There are 5 main components to QTPyLib:


1. Blotter - handles market data retreival and processing.
2. Broker - sends and proccess orders/positions (abstracted layer).
3. Algo - (sub-class of Broker) communicates with the Blotter to pass market data to your strategies, and
proccess/positions orders via Broker.
4. Reports - provides real time monitoring of trades and open opsitions via Web App, as well as a simple REST
API for trades, open positions and market data.
5. Lastly, Your Strategies, which are sub-classes of Algo, handle the trading logic/rules. This is where you’ll
write most of your code.

14 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

Flow Chart

4.2.3 Getting Market Data

Market Data retrieval is done by a piece of software called a Blotter. A Blotter connects to the broker (in QTPyLib’s
case, Interactive Brokers via TWS/IB), handles incoming market data and passes it to the algo for processing.
Blotters optionally (but usually) also take care of storing the market data in a Database for later analysis, back-testing
new strategies, etc.
In QTPyLib’s case, the Blotter handle all of the above, while your algorithms subscribe to the Blotter’s updates via
pub/sub mechanism using ZeroMQ - a blazing fast Message Queue.

4.2. Table of Contents 15


QTPyLib Documentation, Release latest

Note: QTPyLib was designed with a “One Blotter To Rule Them All” design in mind. All your algorithms can
listen to a single Blotter running in the background without a problem and without consuming any unnessecery system
resources. Simply put: do not run multiple Blotters unless you have a very specific reason to do so.

Creating the Database

The first thing you need to do is to create the MySQL database where your Blotter will store tick and minute data for
later use.
Once you’ve created the database, note its name for the next step. The Blotter will automatically create the required
database tables when it runs for the first time.

Writing your Blotter

To get started writing your Blotter, you’ll need to create a Blotter object sub-class and name it.
Then, inililize your Blotter by passing your MySQL credentials and TWS/IBGW port and run it.
# blotter.py
from qtpylib.blotter import Blotter

class MainBlotter(Blotter):
pass # we just need the name

if __name__ == "__main__":
blotter = MainBlotter(
dbhost = "localhost",
dbname = "qtpy",
dbuser = "master",
dbpass = "blaster",
ibport = 4001, # 7496/7497 = TWS, 4001 = IBGateway
)

blotter.run()

Running your Blotter

With IB TWS/GW running, run the Blotter from the command line:
$ python blotter.py

Initilizing via CLI

You can also override the initilized paramters (or ommit this part of the code altogether) and pass runtime parameters
using the command line.
In this case, your code would look something like this:

16 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

# blotter.py
from qtpylib.blotter import Blotter

class MainBlotter(Blotter):
pass # we just need the name

if __name__ == "__main__":
blotter = MainBlotter()
blotter.run()

Then, run the Blotter by passing the parameters via the command line:
$ python blotter.py [--dbport] [--dbname] [--dbuser] [--dbpass] [--ibport] [...]

Available Arguments

Below are all the parameters that can either be set via the Blotter() initilizer or via CLI:
• --symbols CSV database of IB contracts for market data fetching (default: ./symbols.csv)
• --ibport TWS/IBGW Port to use (default: 4001)
• --ibclient TWS/IBGW Client ID (default: 999)
• --ibserver IB TWS/GW Server hostname (default: localhost)
• --zmqport ØMQ Port to use (default: 12345)
• --dbhost MySQL server hostname (default: localhost)
• --dbport MySQL server port (default: 3306)
• --dbname MySQL server database (default: qtpy)
• --dbuser MySQL server username (default: root)
• --dbpass MySQL server password (default: None)
• --dbskip [flag] Skip MySQL logging of market data (default: False)

Instruments CSV

Once your Blotter runs for the first time, you’ll notice that a new file named symbols.csv has been created in the
same directory as your Blotter.
This fill will store all the instruments that algos connecting to this Blotter will request data for. Your blotter will keep
logging market data for these instruments even when you stop your algos so you have continious market data stored
in your database for future research and backtesting (expired product will be deleted automatically from this file).
You can, of course, add or delete unwanted instruments from the CSV file manually at any time – without stopping
your Blotter.
Eample a populated symbols.csv file:
symbol,sec_type,exchange,currency,expiry,strike,opt_type
AAPL,STK,SMART,USD,,0.0,
ES,FUT,GLOBEX,USD,201609,0.0,
NFFX,OPT,SMART,USD,20160819,98.50,PUT

4.2. Table of Contents 17


QTPyLib Documentation, Release latest

This file’s structure is better understood when looked at as a table:


symbol sec_type exchange currency expiry strike opt_type
AAPL STK SMART USD “” 0.0 “”
ES FUT GLOBEX USD 201609 0.0 “”
NFFX OPT SMART USD 20160819 98.50 PUT

With your Blotter running, its time to write your first Algo...

4.2.4 Writing Your Algorithm

When creating your algorithm, there are two functions that handles incoming market data from the running Blotter.
These are on_tick() which is invoked on every tick captured, and on_bar(), which is invoked on every bar
created in the pre-specified resolution. An Instruments Object is being passed to each method when called.
If you need to set some parameters when your strategy starts, simply add an on_start() method to your strategy,
and set your parameters there.
All three methods are optional. You can run logic on start and/or on every tick and/or on every bar event as needed.
Unnecessary can either use pass or be ommited from your strategy code.

Warning: You’re going to lose a lot of money very quickly by running the sample algorithms in this docu-
mentation! Please use the demo account when logging into IB TWS / IB Gateway (user: edemo, password:
demouser).

Basic Algo Structure

Here’s a code for an algo that buys Apple Stock when flat and sells when in position.
# strategy.py
from qtpylib.algo import Algo

class DumbAlgo(Algo):

def on_start(self):
# optional method that gets called once upon start
pass

def on_tick(self, instrument):


# optional method that gets called on every tick received
pass

def on_bar(self, instrument):


# optional method that gets called on every bar received

# buy if position = 0, sell if in position > 0


if instrument.positions['position'] == 0:
instrument.buy(100)
else:
instrument.exit()

if __name__ == "__main__":

18 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

# initialize the algo


strategy = DumbAlgo(
instruments = [ "AAPL" ],
resolution = "1T" # 1Min bar resolution (Pandas "resample" resolutions)
)

# run the algo


strategy.run()

With your Blotter running in the background, run your algo from the command line:
$ python strategy.py

The algo will communicate with the Blotter running in the background and generate orders based on the rules specified.

Note: A trade log will be saved in the database specified in the currently running Blotter and will be available via the
Reporting Web App / API.

Simple MA Cross Over Strategy

While the Blotter running in the background, write and execute your algorithm:
# strategy.py
from qtpylib.algo import Algo

class CrossOver(Algo):

def on_bar(self, instrument):

# get instrument history


bars = instrument.get_bars(window=20)

# make sure we have at least 20 bars to work with


if len(bars) < 20:
return

# compute averages using internal rolling_mean


bars['short_ma'] = bars['close'].rolling_mean(window=10)
bars['long_ma'] = bars['close'].rolling_mean(window=20)

# get current position data


positions = instrument.get_positions()

# trading logic - entry signal


if bars['short_ma'].crossed_above(bars['long_ma'])[-1]:
if not instrument.pending_orders and positions["position"] == 0:

# send a buy signal


instrument.buy(1)

# record values for future analysis


self.record(ma_cross=1)

# trading logic - exit signal

4.2. Table of Contents 19


QTPyLib Documentation, Release latest

elif bars['short_ma'].crossed_below(bars['long_ma'])[-1]:
if positions["position"] != 0:

# exit / flatten position


instrument.exit()

# record values for future analysis


self.record(ma_cross=-1)

if __name__ == "__main__":
strategy = CrossOver(
instruments = [ ("CL", "FUT", "NYMAX", "USD", 201609) ],
resolution = "1H"
)

strategy.run()

With your Blotter running in the background, run your algo from the command line:
$ python strategy.py --log ~/qtpy/

By adding --log ~/qtpy/ we ask that the resulting trade journal be saved in
~/qtpy/STRATEGY_YYYYMMDD.csv for later analysis in additioan to being saved in the database.

Using Multiple Instruments

# strategy.py
from qtpylib.algo import Algo

class BuyStockSellOil(Algo):

def on_bar(self, instrument):

# get instrument object


ES = self.get_instrument('ESU2016_FUT')
CL = self.get_instrument('CLU2016_FUT')

# rotate holding between ES and CL


# yes - this strategy makes no sense :)

es_pos = ES.get_positions()
cl_pos = CL.get_positions()

if es_pos["position"] == 0 and cl_pos["position"] > 0:


ES.buy(1)
CL.exit(1)
elif es_pos["position"] > 0 and cl_pos["position"] == 0:
ES.exit(1)
CL.buy(1)

if __name__ == "__main__":
strategy = BuyStockSellOil(
instruments = [

20 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

("ES", "FUT", "GLOBEX", "USD", 201609),


("CL", "FUT", "NYMAX", "USD", 201609)
],
resolution = "15T"
)

strategy.run()

Initializing Parameters

Sometimes you’d want to set some parameters when you initlize your Strategy. To do so, simply add an on_start()
method to your strategy, and set your parameters there. It will be invoked once when you strategy starts.
# strategy.py
from qtpylib.algo import Algo

class MyStrategy(Algo):

def on_start(self):
self.paramA = "a"
self.paramB = "b"

...

Available Arguments

Below are all the parameters that can either be set via the Algo() or via CLI (all are optional).

Algo Parameters

• instruments List of stock symbols (for US Stocks) / IB Contract Tuples


• resolution Bar resolution (pandas resample resolution: 1T/4H/etc, and K for tick bars).
• tick_window Length of tick lookback window to keep (defaults to 1)
• bar_window Length of bar lookback window to keep (defaults to 100)
• timezone Convert IB timestamps to this timezone, eg. “US/Central” (defaults to UTC)
• preload Preload history upon start (eg. 1H, 2D, etc, or K for tick bars).
• blotter Log trades to MySQL server used by this Blotter (default: auto-detect).
Example:
# strategy.py
...

strategy = MyStrategy(
instruments = [ "AAPL" ],
resolution = "512K", # 512 tick bars
tick_window = 10, # keep last 10 ticks bars

4.2. Table of Contents 21


QTPyLib Documentation, Release latest

bar_window = 500, # keep last 500 (tick) bars


preload = "4H", # pre-load the last 4 hours of tick bar data
timezone = "US/Central", # convert all tick/bar timestamps to "US/Central"
blotter = "MainBlotter" # use this blotter's database to store the trade log
)
strategy.run()

Runtime (CLI) Parameters

• --sms List of numbers to text orders (default: None)


• --log Path to store trade data (default: None)
• --ibport IB TWS/GW Port to use (default: 4001)
• --ibclient IB TWS/GW Client ID (default: 998)
• --ibserver IB TWS/GW Server hostname (default: localhost)
• --blotter Log trades to MySQL server used by this Blotter (default: auto-detect)
• --output Path to save the recorded data (default: None)
Example:
$ python strategy.py --ibport 4001 --log ~/qtpy/ --blotter MainBlotter --sms +15551230987 ...

Back-Testing Using QTPyLib

In addition to live/paper trading, QTPyLib can also be used for back-testing without changing event one line of code,
simply by adding the following arguments when running your algo.

Note: You MUST have the relevant historical data stored in your Blotter’s database in order to run back-tests - which
is also a good reason to keep your Blotter running for all eternity :)
In addition, when backtesting Futures, the Blotter will stream adjusted, continous contracts for the contracts requested,
based on previously captured market data stored in the Database.

• --backtest [flag] Work in Backtest mode (default: False)


• --start Backtest start date (YYYY-MM-DD [HH:MM:SS[.MS])
• --end Backtest end date (YYYY-MM-DD [HH:MM:SS[.MS])
With your Blotter running in the background, run your algo from the command line:
$ python strategy.py --backtest --start 2015-01-01 --end 2015-12-31 -output portfolio.pkl

The resulting back-tested portfolio will be saved in ./portfolio.pkl for later analysis.

Recording Data

You can record data from within your algo and make this data available as a csv/pickle/h5 file. You can record whatever
you want by adding this to your algo code (bar data is recorded automatically):

22 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

self.record(key=value, ...)

Then run your algo with the --output flag:


$ python strategy.py --output path/to/recorded-file.csv

The recorded data (and bar data) will be made availble in ./path/to/recorded-file.csv, which gets updated
in real-time.

Instruments Tuples

When initilizing your algo, you’re required to pass a list of instruments you want to trades. List items can be a Ticker
Symbol String (for US Stocks only) or an Tuple in IB format for other instruments.
Example: US Stocks
instruments = [ "AAPL", "GOOG", "..." ]

For anything other than US Stocks, you must use IB Tuples in the following data information:
(symbol, sec_type, exchange, currency [, expiry [, strike, opt_type]])
Where expiry must be provided for Futures (YYYYMM) and Options (YYYYMMDD) whereas strike and
opt_type must be a provided for Options (PUT/CALL).
Example: UK Stock
instruments = [ ("BARC", "STK", "LSE", "GBP"), (...) ]

Example: S&P E-mini Futures


instruments = [ ("ES", "FUT", "GLOBEX", "USD", 201609), (...) ]

Example: Netflix Option


instruments = [ ("NFLX", "OPT", "SMART", "USD", 20160819, 98.50, "PUT"), (...) ]

Example: Forex (EUR/USD)


instruments = [ ("EUR", "CASH", "IDEALPRO", "USD"), (...) ]

For best practice, its recommended that you use the full IB Tuple structure for all types of instruments:
instruments = [
("AAPL", "STK", "SMART", "USD", "", 0.0, ""),
("BARC", "STK", "LSE", "GBP", "", 0.0, ""),
("ES", "FUT", "GLOBEX", "USD", 201609, 0.0, ""),
("NFLX", "OPT", "SMART", "USD", 20160819, 98.50, "PUT"),
("EUR", "CASH", "IDEALPRO", "USD", "", 0.0, ""),
...
]

4.2. Table of Contents 23


QTPyLib Documentation, Release latest

4.2.5 Reporting Web App / API

QTPyLib comes with a basic reporting web app where you can monitor your trade history and open positions. While
the web app is running, it also exposes a simple REST API for fetching trades, market data, etc to create your own
application.

Note: Since QTPyLib relies on Interactive Brokers for pretty much everything, it’s recommended that you create a
second user for your IB account and use it to login to TWS on your computer or Phone. There you can see the trades
made by your algorithms, use the built-in charts, etc.

Creating a Web App

To get a reporting dashboard up and running, you’ll need to create a Reports object sub-class and name it.
# dashboard.py
from qtpylib.reports import Reports

class Dashboard(Reports):
pass # we just need the name

if __name__ == "__main__":
dashboard = Dashboard(
port = 5000,
blotter = "MainBlotter"
)
dashboard.run()

Running the Web App

While the Blotter running in the background, run your dashboard from the command line:
$ python dashboard.py

>>> Web app password is: a0f36d


>>> Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Point your browser to http://localhost:5000, enter the password, and you should see something like this:

24 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

Initilizing via CLI

You can also override the initilized paramters (or ommit this part of the code altogether) and pass runtime parameters
using the command line.
In this case, your code would look something like this:
# dashboard.py
from qtpylib.reports import Reports

class Dashboard(Reports):
pass # we just need the name

if __name__ == "__main__":
dashboard = Dashboard()
dashboard.run()

Then, run the Blotter by passing the parameters via the command line:
$ python dashboard.py --port 5000 --blotter MainBlotter --nopass

Available Arguments

Below are the parameters that can either be set via the Reports() initilizer or via CLI:
• --port HTTP port to use (default: 5000)
• --host Host to bind the http process to (defaults to localhost)
• --blotter Use this Blotter’s MySQL server settings (default: auto-detect).
• --nopass [flag] Skip password for web app

REST API

With your web app running, a few REST API endpoints becomes accessible using:
$ curl -i -X GET ENDPOINT

Each endpoints returns an Array of JSON objects with the requested information.

Example Response (/trades)

[ {
"algo": "TestStrategy",
"symbol": "ESU2016",
"direction": "LONG",
"quantity": 1,
"entry_time": 1471490411,
"order_type": "MARKET",
"entry_price": 2192.75,
"market_price": 2192.5,
"slippage": -0.25,
"target": 0,

4.2. Table of Contents 25


QTPyLib Documentation, Release latest

"stop": 0,
"exit_time": 1471490411,
"exit_price": 2192.5,
"exit_reason": "SIGNAL",
"realized_pnl": 0.25,
}, ... ]

Available Endpoints

Algo list:
$ http://localhost:5000/algos

Symbol list:
$ http://localhost:5000/symbols

Trade list:
$ http://localhost:5000/trades
$ http://localhost:5000/trades/start_YY-MM-DD/
$ http://localhost:5000/trades/start_YY-MM-DD/end_YY-MM-DD/

Trades for specific Algo:


$ http://localhost:5000/algo/algo_name
$ http://localhost:5000/algo/algo_name/start_YY-MM-DD/
$ http://localhost:5000/algo/algo_name/start_YY-MM-DD/end_YY-MM-DD/

Market data:
$ http://localhost:5000/bars/resolution/symbol
$ http://localhost:5000/bars/resolution/symbol/start_YY-MM-DD/
$ http://localhost:5000/bars/resolution/symbol/start_YY-MM-DD/end_YY-MM-DD/

4.2.6 SMS Notification

QTPyLib supports both automatic trade notifications via SMS and custom messages (for example, when you want to
SMS yourself signals without entering a trade).
To specify the recepients, add the --sms flag when running your algo from the command line:
$ python strategy.py --sms +15551230987 +447781123456 ...

Now, whenever your algo generates a trade or when you send custom SMS, these recepients will receive the notification
to their phone.

Note: To enable this functionality, you need to have an account with either Nexmo or Twilio and set an SMS Provider
for your algo (refer to the SMS Service Provider Setup section below).

Trade Notifications

Trades notifications are enabled by default and will be sent whenever your algo makes a trade, as long as you specified
recepients when running the algo.

26 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

Trade notifications looks like this (followed are made up prices):


11:37:21 UTC
BOT 2x ESU2016 @ 2177.0 MKT
TP 2178.25 / SL 2174.75

----

11:39:29 UTC
SLD 2x ESU2016 @ 2178.25 TGT
PL +1.25 (2m 8s)

----

12:47:29 UTC
SLD 2x ESU2016 @ 2174.50 STP
PL -2.50 (1h 10m 8s)

Custom Notifications

Aside from automatic trade notification, you have your algo send custom messages (for example, when you want to
SMS yourself signals without entering a trade).
To do this, add you need to import the SMS module and add this code to your algo:
self.sms("Look ma, custom text msg...")

SMS Service Provider Setup

To enable this functionality, you need to have an account with either Nexmo or Twilio.
Then, simply create a file named sms.ini in the same directory as your strategy.py file with the following
structure:

SMS Using Nexmo

[nexmo]
key = API_KEY
secret = SECRET_KEY
from = FROM_NUMBER (OPTIONAL)

SMS Using Twilio

[twilio]
sid = ACCOUNT_SID
token = AUTH_TOKEN
from = FROM_NUMBER

Note: If your sms.ini file contains both services, QTPyLib will use the first one listed.

4.2. Table of Contents 27


QTPyLib Documentation, Release latest

4.2.7 Technical Indicators

Although you can import technical indicator libraries such as the excellent TA-Lib and use them in your strategies,
QTPyLib does comes bundled with some common indicators that work as Pandas Objects.

ATR

bars['atr'] = bars.atr(window=14 [, exp=False])


...

Bollinger Bands

bb = bars.bollinger_bands(window=20, stds=2)

bars['bb_upper'] = bb['upper']
bars['bb_lower'] = bb['lower']
bars['bb_mid'] = bb['mid']
...

Weighted Bollinger Bands

wbb = bars.weighted_bollinger_bands(window=20, stds=2)

bars['wbb_upper'] = wbb['upper']
bars['wbb_lower'] = wbb['lower']
bars['wbb_mid'] = wbb['mid']
...

CCI

bars['cci'] = bars.cci(window=14)
...

Crossed Above/Below

bars['sma'] = bars['close'].rolling_mean(10)

if bars['close'].crossed_above(bars['sma']):
...

if bars['close'].crossed_below(bars['sma']):
...

IBS

bars['ibs'] = bars.ibs()
...

28 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

Implied Volatility

bars['iv'] = bars.implied_volatility(window=252)
...

Keltner Channel

kc = bars.keltner_channel(window=14, atrs=2)

bars['kc_upper'] = kc['upper']
bars['kc_lower'] = kc['lower']
bars['kc_mid'] = kc['mid']
...

MACD

macd = bars.macd(fast=3, slow=10, smooth=16)

bars['macd'] = macd['macd']
bars['macd_signal'] = macd['signal']
bars['macd_hist'] = macd['histogram']
...

Moving Average

Simple Moving Average

Shorthand for bars.rolling_mean(...)


bars['sma'] = bars.sma(window=200 [, min_periods=None])
...

Weighted Moving Average

Shorthand for bars.rolling_weighted_mean(...)


bars['wma'] = bars.wma(window=200 [, min_periods=None])
...

Hull Moving Average

Shorthand for bars.hull_moving_average(...)


bars['hma'] = bars.hma(window=200 [, min_periods=None])
...

4.2. Table of Contents 29


QTPyLib Documentation, Release latest

Price Indicators

Mid: (High + Low) / 2

bars['mid'] = bars.mid_price()
...

Typical: (High + Low + Close) / 3

bars['typical'] = bars.typical_price()
...

Rolling Indicators

Min

bars['min'] = bars.rolling_min(window=14 [, min_periods=None])


...

Max

bars['max'] = bars.rolling_max(window=14 [, min_periods=None])


...

Mean

bars['sma'] = bars.rolling_mean(window=200 [, min_periods=None])


...

Standard Deviation

bars['std'] = bars.rolling_std(window=200 [, min_periods=None])


...

Weighted Mean

bars['wma'] = bars.rolling_weighted_mean(window=200 [, min_periods=None])


...

Returns

bars['returns'] = bars.returns()
...

30 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

Log Returns

bars['log_returns'] = bars.log_returns()
...

ROC

bars['roc'] = bars.roc(window=14)
...

RSI

bars['rsi'] = bars.rsi(window=14)
...

Session

This isn’t an indicator, but rather a utility that trims the bars to a specified “Session” (useful when wanting to work,
for example, with the most recent PIT or GLOBEX session to calculate VWAP, etc.).
# make sure to specity timezone="US/Central" for your algo
# otherwise, the default timezone is UTC

# pit session
bars = bars.session(start='08:30', end='15:15')

# globex session
bars = bars.session(start='17:00', end='16:00')
...

Stochastics

bars['stoch'] = bars.stoch(window=14, slow=False, slow_ma=3)


...

True Range

bars['tr'] = bars.true_range()
...

VWAP

bars['vwap'] = bars.vwap(bars)
...

4.2. Table of Contents 31


QTPyLib Documentation, Release latest

4.2.8 Futures Trading

Most Traded Contract Expiration

If you want to always trade the most active future contract (based on the previous day’s volume and open interest),
you can do so by using the futures.get_active_contract() function to construct your IB contract tuples
specified in your algo.
# strategy.oy
...

from qtpylib import futures

if __name__ == "__main__":
# get most active ES contract
ACTIVE_MONTH = futures.get_active_contract("ES")

strategy = CrossOver(
instruments = [ ("ES", "FUT", "GLOBEX", "USD", ACTIVE_MONTH, 0.0, "") ],
...
)

...

Note: This functionality currently works for future contracts traded on the CME only (including CME, GLOBEX,
CBOT, NYMEX and COMEX).

Contract Margin Requriments

When you want to know a futures contract’s margin requirements, you can call futures.get_ib_margin(...)
to get that information. New data is fetched from IB id cache file doesn’t exist or if it’s older than 24 hours.
# strategy.oy
...

from qtpylib import futures

def on_bar(self, instrument):


margin = futures.get_ib_margin('path/to/cache_file.pkl', "NQ", "GLOBEX")

if margin['intraday_initial'] > self.account['AvailableFunds']:


print("Not enough funds to trade this contract")
return

"""
margin returns a dict with the following data:

{
'class': 'NQ',
'currency': 'USD',
'description': 'E-mini NASDAQ 100 Futures',
'exchange': 'GLOBEX',

32 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

'has_options': True,
'intraday_initial': 2250.0,
'intraday_maintenance': 1800.0,
'overnight_initial': 4500.0,
'overnight_maintenance': 3600.0,
'symbol': 'NQ'
}

"""

This information is also available using instrument.get_futures_margin_requirement() from within


your strategies (in this case, the cache file will be saved as ib_margins.pkl in your working directory).

4.2.9 API Reference

Instrument API

The Instrument object is passed to the on_tick(...) and on_bar(...) methods in your strategy:
# startegy.py
def on_tick(self, instrument):
instrument.MethodName(...)

def on_bar(self, instrument):


instrument.MethodName(...)

class qtpylib.instrument.Instrument
A string subclass that provides easy access to misc symbol-related methods and information.
get_bars(lookback=None, as_dict=False)
Get bars for this instrument
Parameters
lookback [int] Max number of bars to get (None = all available bars)
as_dict [bool] Return a dict or a pd.DataFrame object
Retruns
bars [pd.DataFrame / dict] The bars for this instruments
get_ticks(lookback=None, as_dict=False)
Get ticks for this instrument
Parameters
lookback [int] Max number of ticks to get (None = all available ticks)
as_dict [bool] Return a dict or a pd.DataFrame object
Retruns
bars [pd.DataFrame / dict] The ticks for this instruments
order(direction, quantity, **kwargs)
Send an order for this instrument
Parameters
direction [string] Order Type (BUY/SELL, EXIT/FLATTEN)
quantity [int] Order quantity

4.2. Table of Contents 33


QTPyLib Documentation, Release latest

Optional
limit_price [float] In case of a LIMIT order, this is the LIMIT PRICE
expiry [int] Cancel this order if not filled after n seconds (default 60 seconds)
order_type [string] Type of order: Market (default), LIMIT (default when limit_price is
passed), MODIFY (required passing or orderId)
orderId [int] If modifying an order, the order id of the modified order
target [float] target (exit) price
initial_stop [float] price to set hard stop
trail_stop_at [float] price at which to start trailing the stop
trail_stop_by [float] % of trailing stop distance from current price
ticksize [float] If using traling stop, pass the tick size for the instruments so you won’t try to
buy ES at 2200.128230 :)
market_order(direction, quantity, **kwargs)
Shortcut for instrument.order(...) and accepts all of its optional parameters
Parameters
direction [string] Order Type (BUY/SELL, EXIT/FLATTEN)
quantity [int] Order quantity
limit_order(direction, quantity, price, **kwargs)
Shortcut for instrument.order(...) and accepts all of its optional parameters
Parameters
direction [string] Order Type (BUY/SELL, EXIT/FLATTEN)
quantity [int] Order quantity
price [float] Limit price
buy(quantity, **kwargs)
Shortcut for instrument.order("BUY", ...) and accepts all of its optional parameters
Parameters
quantity [int] Order quantity
buy_market(quantity, **kwargs)
Shortcut for instrument.order("BUY", ...) and accepts all of its optional parameters
Parameters
quantity [int] Order quantity
buy_limit(quantity, price, **kwargs)
Shortcut for instrument.order("BUY", ...) and accepts all of its optional parameters
Parameters
quantity [int] Order quantity
price [float] Limit price
sell(quantity, **kwargs)
Shortcut for instrument.order("SELL", ...) and accepts all of its optional parameters
Parameters

34 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

quantity [int] Order quantity


sell_market(quantity, **kwargs)
Shortcut for instrument.order("SELL", ...) and accepts all of its optional parameters
Parameters
quantity [int] Order quantity
sell_limit(quantity, price, **kwargs)
Shortcut for instrument.order("SELL", ...) and accepts all of its optional parameters
Parameters
quantity [int] Order quantity
price [float] Limit price
exit()
Shortcut for instrument.order("EXIT", ...) (accepts no parameters)
flatten()
Shortcut for instrument.order("FLATTEN", ...) (accepts no parameters)
get_contract()
Get contract object for this instrument
Retruns
contract [Object] IB Contract object
get_positions(attr=None)
Get the positions data for the instrument
Optional
attr [string] Position attribute to get (optional attributes: symbol, position, avgCost, ac-
count)
Retruns
positions [dict (positions) / float/str (attribute)] positions data for the instrument
get_portfolio()
Get portfolio data for the instrument
Retruns
contract [dict] portfolio data for the instrument
get_orders()
Get orders for the instrument
Retruns
contract [list] list of order data as dict
get_pending_orders()
Get pending orders for the instrument
Retruns
contract [list] list of pending order data as dict
get_active_order(order_type=’STOP’)
Get artive order id for the instrument by order_type
Optional

4.2. Table of Contents 35


QTPyLib Documentation, Release latest

order_type [string] the type order to return: STOP (default), LIMIT, MARKET
Retruns
contract [object] IB Order object of instrument
get_orderbook()
Get orderbook for the instrument
Retruns
contract [pd.DataFrame] orderbook DataFrame for the instrument
get_symbol()
Get symbol of this instrument
Retruns
contract [pd.DataFrame] orderbook DataFrame for the instrument
modify_order(orderId, quantity=None, limit_price=None)
Modify quantity and/or limit price of an active order for the instrument
Parameters
orderId [int] the order id to modify
Optional
quantity [int] the required quantity of the modified order
limit_price [int] the new limit price of the modified order
get_margin_requirement()
Get margin requirements for intrument (futures only)
Retruns
margin [dict] margin requirements for instrument (all values are None for non-futures in-
struments)
get_margin_max_contracts(overnight=True)
Get maximum contracts allowed to trade baed on required margin per contract and current account balance
(futures only)
Parameters
overnight [bool] Calculate based on Overnight margin (set to False to use Intraday margin
req.)
Retruns
contracts [int] maximum contracts allowed to trade (returns None for non-futures)
symbol
(Property) Shortcut to self.get_symbol()
contract
(Property) Shortcut to self.get_contract()
positions
(Property) Shortcut to self.get_positions()
portfolio
(Property) Shortcut to self.get_portfolio()

36 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

orders
(Property) Shortcut to self.get_orders()
pending_orders
(Property) Shortcut to self.get_pending_orders()
orderbook
(Property) Shortcut to self.get_orderbook()
margin_requirement
(Property) Shortcut to self.get_margin_requirement()
margin_max_contracts
(Property) Shortcut to self.get_margin_max_contracts()

Algo API

Algo is a Sub-Class of Broker and the Parent Class for your strategies. Aside from algo.run(...), all the other
methods should be called from within your strategy via self.MethodName(...).
For example:
# startegy.py

# record something
self.record(key=value)

# send custom text


self.sms("message text")

# get instrument object


instrument = self.get_instrument("SYMBOL")

Blotter API

Reports API

Broker API

Broker is the Parent Class of Algo, which, in turn, is the Parent Class for your strategies. All the following methods
are available from within your strategy via self.MethodName(...)‘.

4.2.10 Run as a Linux Service

In many cases, it may be useful to run your code as a system service (aka “daemon”), so you can start/stop it using a
Cron job, monitor it using Monit, etc. The following is a quick guide on how to turn any Python script into a system
service on Linux and Unix machines.
The first step is to create your Python script (for this example we’ll use blotter.py).

Create a systemd Service File

The next step is to create a systemd service file to daemonize blotter.py.


From the command line, type:

4.2. Table of Contents 37


QTPyLib Documentation, Release latest

$ sudo nano /lib/systemd/system/qtpylib-blotter.service

...and add in the following:


[Unit]
Description=QTPyLib Blotter
After=multi-user.target

[Service]
Type=idle
ExecStart=/PATH/TO/PYTHON /PATH/TO/blotter.py >/dev/null 2>&1

[Install]
WantedBy=multi-user.target

In order to store the Blotter’s output in a log file, change the ExecStart line to:
ExecStart=/path/to/python /path/to/blotter.py > /path/to/blotter.log 2>&1

Note: In most cases the Python executable is found under /usr/bin/python, but it can be located elsewhere
(for example: /home/user/anaconda3/bin/python). You can run which python to get the path to the
System’s default Python executable.

Next, change the permission on that file to 644:


$ sudo chmod 644 /lib/systemd/system/qtpylib-blotter.service

Enable The Service using systemctl

Now the system file has been defined, we need to reload systemctl:
$ sudo systemctl daemon-reload
$ sudo systemctl enable qtpylib-blotter.service

Start/Stop Your Service

Start the service


$ sudo service qtpylib-blotter start

Stop the service


$ sudo service qtpylib-blotter stop

Check the service’s status


$ sudo service qtpylib-blotter status

You shoud see something like this:


sudo service qtpylib-blotter status
qtpylib-blotter.service - QTPyLib Blotter
Loaded: loaded (/lib/systemd/system/qtpylib-blotter.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2016-08-22 07:09:06 UTC; 12s ago
Main PID: 26737 (python)

38 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

CGroup: /system.slice/qtpylib-blotter.service
-26737 /usr/bin/python /home/user/blotter.py

4.2.11 Legal Notice

QTPyLib is not a product of Interactive Brokers, nor is it affiliated with Interactive Brokers.
QTPyLib is distributed under the GNU Lesser General Public License v3.0.

License Agreement

GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007


Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Everyone is permitted to copy and
distribute verbatim copies of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions
listed below.
0. Additional Definitions.
As used herein, “this License” refers to version 3 of the GNU Lesser
General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License.
“The Library” refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An “Application” is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library
is deemed a mode of using an interface provided by the Library.
A “Combined Work” is a work produced by combining or linking an
Application with the Library. The particular version of the Library with which the Combined Work was made is also
called the “Linked Version”.
The “Minimal Corresponding Source” for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that,
considered in isolation, are based on the Application, and not on the Linked Version.
The “Corresponding Application Code” for a Combined Work means the
object code and/or source code for the Application, including any data and utility programs needed for reproducing
the Combined Work from the Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a

4.2. Table of Contents 39


QTPyLib Documentation, Release latest

facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument
passed when the facility is invoked), then you may convey a copy of the modified version:
a) under this License, provided that you make a good faith effort to ensure that, in the event
an Application does not supply the function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of this License applicable to
that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if
the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros,
inline functions and templates (ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the Library is used in it and
that the Library and its use are covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work
and reverse engineering for debugging such modifications, if you also do each of the following:
a) Give prominent notice with each copy of the Combined Work that the Library is used in it
and that the Library and its use are covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license document.
c) For a Combined Work that displays copyright notices during execution, include the copy-
right notice for the Library among these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
4. Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this License,
and the Corresponding Application Code in a form suitable for, and under terms
that permit, the user to recombine or relink the Application with a modified ver-
sion of the Linked Version to produce a modified Combined Work, in the manner
specified by section 6 of the GNU GPL for conveying Corresponding Source.
1) Use a suitable shared library mechanism for linking with the Library. A suit-
able mechanism is one that (a) uses at run time a copy of the Library already
present on the user’s computer system, and (b) will operate properly with a mod-
ified version of the Library that is interface-compatible with the Linked Version.
e) Provide Installation Information, but only if you would otherwise be required to provide such
information under section 6 of the GNU GPL, and only to the extent that such information
is necessary to install and execute a modified version of the Combined Work produced by
recombining or relinking the Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany the Minimal Corresponding
Source and Corresponding Application Code. If you use option 4d1, you must provide the
Installation Information in the manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.)
5. Combined Libraries.

40 Chapter 4. Legal Stuff


QTPyLib Documentation, Release latest

You may place library facilities that are a work based on the
Library side by side in a single library together with other library facilities that are not Applications and are not covered
by this License, and convey such a combined library under terms of your choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based on the Library, un-
combined with any other library facilities, conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it is a work based on the
Library, and explaining where to find the accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present
version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any
later version” applies to it, you have the option of following the terms and conditions either of that published version
or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a
version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General
Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall apply, that proxy’s public statement of
acceptance of any version is permanent authorization for you to choose that version for the Library.

4.2. Table of Contents 41


QTPyLib Documentation, Release latest

42 Chapter 4. Legal Stuff


Index

B L
buy() (qtpylib.instrument.Instrument method), 34 limit_order() (qtpylib.instrument.Instrument method), 34
buy_limit() (qtpylib.instrument.Instrument method), 34
buy_market() (qtpylib.instrument.Instrument method), 34 M
margin_max_contracts (qtpylib.instrument.Instrument at-
C tribute), 37
contract (qtpylib.instrument.Instrument attribute), 36 margin_requirement (qtpylib.instrument.Instrument at-
tribute), 37
E market_order() (qtpylib.instrument.Instrument method),
exit() (qtpylib.instrument.Instrument method), 35 34
modify_order() (qtpylib.instrument.Instrument method),
F 36
flatten() (qtpylib.instrument.Instrument method), 35
O
G order() (qtpylib.instrument.Instrument method), 33
orderbook (qtpylib.instrument.Instrument attribute), 37
get_active_order() (qtpylib.instrument.Instrument
orders (qtpylib.instrument.Instrument attribute), 36
method), 35
get_bars() (qtpylib.instrument.Instrument method), 33 P
get_contract() (qtpylib.instrument.Instrument method),
35 pending_orders (qtpylib.instrument.Instrument attribute),
get_margin_max_contracts() (qt- 37
pylib.instrument.Instrument method), 36 portfolio (qtpylib.instrument.Instrument attribute), 36
get_margin_requirement() (qtpylib.instrument.Instrument positions (qtpylib.instrument.Instrument attribute), 36
method), 36
get_orderbook() (qtpylib.instrument.Instrument method), S
36 sell() (qtpylib.instrument.Instrument method), 34
get_orders() (qtpylib.instrument.Instrument method), 35 sell_limit() (qtpylib.instrument.Instrument method), 35
get_pending_orders() (qtpylib.instrument.Instrument sell_market() (qtpylib.instrument.Instrument method), 35
method), 35 symbol (qtpylib.instrument.Instrument attribute), 36
get_portfolio() (qtpylib.instrument.Instrument method),
35
get_positions() (qtpylib.instrument.Instrument method),
35
get_symbol() (qtpylib.instrument.Instrument method), 36
get_ticks() (qtpylib.instrument.Instrument method), 33

I
Instrument (class in qtpylib.instrument), 33

43

You might also like