Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 0 additions & 70 deletions docs/authentication.md

This file was deleted.

71 changes: 13 additions & 58 deletions docs/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

You will use an instance of this class to interact with API.

Each instance of this class will have one connection to API, either live or demo endpoint.
Each instance of this class will have one connection to API, either QUOTE or TRADE.

The client class is driven from Twisted ClientService class, and it abstracts away all the connection / reconnection complexities from you.

Expand All @@ -12,79 +12,34 @@ Let's create an isntance of Client class:

```python

from ctrader_open_api import Client, Protobuf, TcpProtocol, Auth, EndPoints
from ctrader_fix import *

client = Client(EndPoints.PROTOBUF_DEMO_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)
client = Client(config["Host"], config["Port"], ssl = config["SSL"])

```

It's constructor has several parameters that you can use for controling it behavior:

* host: The API host endpoint, you can use either EndPoints.PROTOBUF_DEMO_HOST or EndPoints.PROTOBUF_LIVE_HOST
* host: The API host endpoint, you can get it from your cTrader FIX settings

* port: The API host port number, you can use EndPoints.PROTOBUF_PORT
* port: The API host port number, you can get it from your cTrader FIX settings

* protocol: The protocol that will be used by client for making connections, use imported TcpProtocol
* ssl: It't bool flag, if Yes client will use SSL for connection otherwise it will use plain TCP connection

* numberOfMessagesToSendPerSecond: This is the number of messages that will be sent to API per second, set it based on API limitations or leave the default value
***The SSL connection is not working for now***

There are three other optional parameters which are from Twisted client service, you can find their detail here: https://twistedmatrix.com/documents/current/api/twisted.application.internet.ClientService.html

### Sending Message
### Callbacks

To send a message you have to first create the proto message, ex:

```python
# Import all message types
from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *
from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *
from ctrader_open_api.messages.OpenApiMessages_pb2 import *
from ctrader_open_api.messages.OpenApiModelMessages_pb2 import *

# ProtoOAApplicationAuthReq message
applicationAuthReq = ProtoOAApplicationAuthReq()
applicationAuthReq.clientId = "Your App Client ID"
applicationAuthReq.clientSecret = "Your App Client secret"

```

After you created the message and populated its fields, you can send it by using Client send method:

```python
deferred = client.send(applicationAuthReq)
```

The client send method returns a Twisted deferred, it will be called when the message response arrived, the callback result will be the response proto message.

If the message send failed, the returned deferred error callback will be called, to handle both cases you can attach two callbacks for getting response or error:

```python
def onProtoOAApplicationAuthRes(result):
print(result)

def onError(failure):
print(failure)

deferred.addCallbacks(onProtoOAApplicationAuthRes, onError)
```
For more about Twisted deferreds please check their documentation: https://docs.twistedmatrix.com/en/twisted-16.2.0/core/howto/defer-intro.html

### Canceling Message

You can cancel a message by calling the returned deferred from Client send method Cancel method.

If the message is not sent yet, it will be removed from the messages queue and the deferred Errback method will be called with CancelledError.

If the message is already sent but the response is not received yet, then you will not receive the response and the deferred Errback method will be called with CancelledError.

If the message is already sent and the reponse is received then canceling it's deferred will not have any effect.

### Other Callbacks

The client class has some other optional general purpose callbacks that you can use:
To use your client you have to set it's call backs:

* ConnectedCallback(client): This callback will be called when client gets connected, use client setConnectedCallback method to assign a callback for it

* DisconnectedCallback(client, reason): This callback will be called when client gets disconnected, use client setDisconnectedCallback method to assign a callback for it

* MessageReceivedCallback(client, message): This callback will be called when a message is received, it's called for all message types, use setMessageReceivedCallback to assign a callback for it

Use the connected call back to send a logon message.

And after logon use your message received call back to continue your interaction with API.
50 changes: 50 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
### Config

When you create a request message you have to pass a config, this config should be a dictionary like object with these keys:

* Host: The FIX host that will be used for client connection
* Port: The port number of host
* SSL: true/false, this can be used by client if SSL connected is required
* Username: Your cTrader trading account number
* Password: Your cTrader trading account password
* BeginString: Message begin string (FIX.4.4)
* SenderCompID: Your cTrader FIX SenderCompID
* SenderSubID: Your cTrader FIX SenderSubID (QUOTE/TRADE)
* TargetCompID: Your cTrader FIX TargetCompID (cServer),
* TargetSubID: Your cTrader FIX TargetSubID (QUOTE),
* HeartBeat: The heartbeat seconds (30)

You can get the values for most of them from your cTrader FIX settings.

You can use a JSON file to save your configuration, check our samples.

### JSON Sample

```json
{
"Host": "h51.p.ctrader.com",
"Port": 5201,
"SSL": false,
"Username": "3279204",
"Password": "3279204",
"BeginString": "FIX.4.4",
"SenderCompID": "demo.icmarkets.3279203",
"SenderSubID": "QUOTE",
"TargetCompID": "cServer",
"TargetSubID": "QUOTE",
"HeartBeat": "30"
}
```

You can use it like this:

```python
with open("config.json") as configFile:
config = json.load(configFile)

# For client
client = Client(config["Host"], config["Port"], ssl = config["SSL"])

# For request messages
logonRequest = LogonRequest(config)
```
72 changes: 33 additions & 39 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,59 @@
### Introduction

A Python package for interacting with cTrader Open API.
A Python package for interacting with cTrader FIX API.

This package is developed and maintained by Spotware.

You can use OpenApiPy on all kinds of Python apps, it uses Twisted to send and receive messages asynchronously.
You can use cTraderFix on all kinds of Python apps, it uses Twisted to send and receive messages asynchronously.

Github Repository: https://github.com/spotware/OpenApiPy
Github Repository: https://github.com/spotware/cTraderFixPy

### Installation

You can install OpenApiPy from pip:
You can install cTraderFix from pip:

```
pip install ctrader-open-api
pip install ctrader-fix
```

### Usage

```python

from ctrader_open_api import Client, Protobuf, TcpProtocol, Auth, EndPoints
from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *
from ctrader_open_api.messages.OpenApiCommonMessages_pb2 import *
from ctrader_open_api.messages.OpenApiMessages_pb2 import *
from ctrader_open_api.messages.OpenApiModelMessages_pb2 import *
from twisted.internet import reactor

hostType = input("Host (Live/Demo): ")
host = EndPoints.PROTOBUF_LIVE_HOST if hostType.lower() == "live" else EndPoints.PROTOBUF_DEMO_HOST
client = Client(host, EndPoints.PROTOBUF_PORT, TcpProtocol)

def onError(failure): # Call back for errors
print("Message Error: ", failure)

def connected(client): # Callback for client connection
print("\nConnected")
# Now we send a ProtoOAApplicationAuthReq
request = ProtoOAApplicationAuthReq()
request.clientId = "Your application Client ID"
request.clientSecret = "Your application Client secret"
# Client send method returns a Twisted deferred
deferred = client.send(request)
# You can use the returned Twisted deferred to attach callbacks
# for getting message response or error backs for getting error if something went wrong
# deferred.addCallbacks(onProtoOAApplicationAuthRes, onError)
deferred.addErrback(onError)

def disconnected(client, reason): # Callback for client disconnection
print("\nDisconnected: ", reason)

def onMessageReceived(client, message): # Callback for receiving all messages
print("Message received: \n", Protobuf.extract(message))

# Setting optional client callbacks
from inputimeout import inputimeout, TimeoutOccurred
import json
from ctrader_fix import *

# Callback for receiving all messages
def onMessageReceived(client, responseMessage):
print("Received: ", responseMessage.getMessage().replace("�", "|"))
messageType = responseMessage.getFieldValue(35)
if messageType == "A":
print("We are logged in")

# Callback for client disconnection
def disconnected(client, reason):
print("Disconnected, reason: ", reason)

# Callback for client connection
def connected(client):
print("Connected")
logonRequest = LogonRequest(config)
send(logonRequest)

# you can use two separate config files for QUOTE and TRADE
with open("config-trade.json") as configFile:
config = json.load(configFile)

client = Client(config["Host"], config["Port"], ssl = config["SSL"])

# Setting client callbacks
client.setConnectedCallback(connected)
client.setDisconnectedCallback(disconnected)
client.setMessageReceivedCallback(onMessageReceived)
# Starting the client service
client.startService()
# Run Twisted reactor
reactor.run()

```
Expand Down
23 changes: 23 additions & 0 deletions docs/receiving-messages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Response Message

Whenever client receives a FIX message it calls the "MessagedReceived" callback with the message.

The message parameter of callback is not a plain string, it's an instance of ResponseMessage type.

ResponseMessage class allows you to easily access each field of a response message.

### Getting Message Field Values

To get a field value you can use the response message GetFieldValue method, it takes the FIX field number and returns the value(s).

The GetFieldValue can return three types of values:

* String: When there is only one field of your provided field number on the message it returns that field value

* List: If the field is repetitive like symbol IDs or names, then it returns a list, all of those fields values will be inside that list

* None: if there was no such field inside the message

### Getting Raw Message

If you want to get the raw string of reponse message, you can call the response message getMessage method.
40 changes: 40 additions & 0 deletions docs/sending-messages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
### Messages

The package has a class for each of the cTrader FIX API client side messages.

You have to use those classes to send request messages.

To set fields of a message you should use message instance attributes and use exact field names that are defined on cTrader FIX Engine, Rules of Engagement document.

### Examples

Let's create some messages:

```python
# All mesages contructors requires the config to be passes a parameter
logonRequests = LogonRequest(config)

securityListRequest = SecurityListRequest(config)
securityListRequest.SecurityReqID = "A"
securityListRequest.SecurityListRequestType = 0

newOrderSingle = NewOrderSingle(config)
newOrderSingle.ClOrdID = "B"
newOrderSingle.Symbol = 1
newOrderSingle.Side = 1
newOrderSingle.OrderQty = 1000
newOrderSingle.OrdType = 1
newOrderSingle.Designation = "From FIX"
```

### Sending

To send a message you must use the client send method:

```python
# It returns a Twisted diferred
diferred = client.send(request)
diferred.addCallback(lambda _: print("\nSent: ", request.getMessage(client.getMessageSequenceNumber()).replace("", "|")))
```

You can only call the client send method from OnMessageReceived call back or connected callback.
Loading