Version: 0.1.3-SNAPSHOT
Get started
Overview
Trading API (TAPI) is a part of the standard Consorsbank trading application ActiveTrader / ActiveTrader Pro. It allowes to write user managed application for the specific trading activities. TAPI support pull / push requests and based on the Google Remote Procedure Call (GRPC) technology.
With help of the TAPI you have an access to the accounts, orders, depots and market data information.
|
Important
This documentation is the description of the early version of Trading API. It’s not final and it’s subject to change. With the lookback to the new BaFin regulation it’s especially important to understand that the ordering part of the TAPI can be partially changed to fullfil new law directives. |
Additional information and discussions can be found there. Please contact to the support team to get access to this part of the community.
Requirements
-
Active Trader / Active Trader Pro with Java 8 64 bits, minimum 8Gb RAM
-
Client Java 8 or higher 64 bits
License
Trading-API is licensed under Apache 2.0 license.
The license and notice texts can be found in the delivered LICENSE and NOTICE.TXT files.
Communication
GRPC technology uses one connection to transfer all necessary data beetwen client and ActiveTrader. As developer you don’t need to care about communication. All low level communication, security and converting functions takes TAPI engine. You can concentrate on the high level functions and bussines logic of the application.
Security
TAPI uses HTTP/2 protocol with RSA protection. RSA self signed certificate can be generated directly in the ActiveTrader application. Typical use case is to use user application from same PC, but it’s also possible to connect from the remote machine.
|
Important
To accept self signed certificate from the user application is necessary to use trusted part of the RSA keys (Trust Certificate) by the connection initialization in the client application. This certificate can be exported from the ActiveTrading application. |
To provide users access control can be used secret string. That’s an equivalent of password. Secret is defined in the Active Trader and used only for validation. User application sends secret to the ActiveTrader. If the validation in the ActiveTrader is passed then ActiveTrader generates a session access token and returns it to the user application. With this token is possible to execute other requests. After end of processing the token should be invalidated.
|
Important
We don’t keep secret data in the configuration. Only double MD5 hash of the secret + solt is stored in the configuration. As result we can’t restore the secret. For more information see Defense against rainbow tables |
Configuration
To activate TAPI is need to complete next steps:
| 1 | Select Trading-API settings in the configuration |
| 2 | Activate TAPI checkbox |
| 3 | Optional: if key exists, press [GENERATE NEW KEY] button |
In the opened dialog
| 1 | Enter or correct key settings |
| 2 | Press [GENERATE NEW KEY] button and wait unil new key is generated |
| 3 | Press [OK] button to accept new settings |
After confirmation of the new settings TAPI will be activated.
|
Warning
In some cases if any initialization errors are appear, the TAPI activation indication in the status bar of the application will be red. To check activation problems move mouse cursor over this indication and check tooltip for the error. |
Before to start using client application, it’s need to export trusted certificate from ActiveTrader.
| 1 | Set secret for an access control. Longer string is better. |
| 2 | Press [EXPORT TRUST CERTIFICATE] and store file (for example with name: roots.pem) to the location where client application can use it. |
Usage of the Trading API
Source code
An example aplication is delivered with precompiled GRPC libraries. If you want to generate source code by youself you can use protobuf files from protobuf directory. Please refer to the Java Generated Code Reference.
Initialization
To initialize client application and connect to the ActiveTrader with help of TAPI you have to process next steps:
|
Important
All examples are avialable as a sorce code and can be found in the specific folders. Input point is the file TestClient.java To start examples you have to put into start parameters full path to the trust certificate and secret. For example: "C:\PathToTrustCert\roots.pem 1234567" |
Initialize the root GRPC engine with trusted certificate, exported from configuration dialog of the ActiveTrader.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private String accessToken = "";
/**
* Test client.
*/
public static void main(String[] args) throws Exception {
if (args.length<2) {
System.err.println("Please generate key in AT and "
+ "put location of the trust certificate and secret as arguments");
System.exit(-1);
}
File caFile = new File(args[0]); (1)
if (!caFile.isFile()) { (2)
System.err.println("File: "+caFile+" does not exist");
System.exit(-1);
}
String server = "localhost"; (3)
int port = 40443;
System.err.println("Connecting... "+server+":"+port);
try (TestClient client = new TestClient(server, port, caFile, args[1])) { (4)
// ...
} catch (Exception e) {
e.printStackTrace();
}
}
public TestClient(String host, int port, File caFile, String secret) throws SSLException {
this(NettyChannelBuilder.forAddress(host, port)
.negotiationType(NegotiationType.TLS)
.sslContext(GrpcSslContexts.forClient().trustManager(caFile).build())
.build());
accessToken = login(secret);
if (accessToken.isEmpty()) {
// Error
}
}
| 1 | Get trusted certificate location as a parameter of the command line |
| 2 | Check if a file of the cetrificates exists |
| 3 | Define connection settings |
| 4 | Initialize GRPC connection |
Services and functions definition
After an initialization is GRPC ready and it can be used for the building service stubs to operate with TAPI services. Stubs are sets of service functions with help of then is possible to access data and execute user actions. They are very similar to the normal programming functions with small differences.
-
Each remote function can have one (and only one) input parameter.
-
Each remote function can have one (and only one) result parameter.
-
The function can send data asynchronically
Functions can be simple (one request → one reply), server sends events (one request from client → many replies from server), client sends events (many requests from client → one reply from server) or server and clients sends events (many requests from client → many replies from server). TAPI uses only first and second types of functions. First type of the function used for the simple user activity (pull) and second type for subcriptions or streaming (push).
Services and functions are defined in the special files as protobuf protocol v.3
1
2
3
4
service ServiceName { (1)
rpc SimpleFunction(ClientParameterType1) returns (ServerParameterType1); (2)
rpc PushFunction(ClientParameterType2) returns (stream ServerParameterType2); (3)
}
| 1 | ServiceName is service stub name. This name will used for the access to the service functions |
| 2 | SimpleFunction is simple request / reply function. |
| 3 | PushFunction is push function with one request and streams data from the server. Please check stream keyword before ServerParameterType2 |
|
Important
You don’t need to use protobuf files directly, but it’s good idea to know a syntax of the the protocol. These files are need if you want to use TAPI with other progaming languages. grpc.io conatains all necessary infomation about code generation and usage for all supported programming languages. |
Create services
There are two types of the service functions: blocking and unblocking service functions. Blocking service functions are used for the synchronical answer from the function and similar to the typical program functions. By call of the blocking functions, program waits until a result of the function is arrived. It can produce timeouts by the execution. Unblocking function are used for the background processing. In this case a program don’t wait until result is arrived and listen for the result asynchronically. This type of the stubs is used for the push functions. For more information please refer to the grpc.io web site.
For blocking calls used blocking service stubs, for asynchronical calls unblocking service stubs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private final ManagedChannel channel;
private final AccessServiceGrpc.AccessServiceBlockingStub accessServiceBlockingStub;
private final SecurityServiceGrpc.SecurityServiceBlockingStub securityServiceBlockingStub;
private final SecurityServiceGrpc.SecurityServiceStub securityServiceStub;
private final StockExchangeServiceGrpc.StockExchangeServiceBlockingStub stockExchangeServiceBlockingStub;
private final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub;
private final AccountServiceGrpc.AccountServiceStub accountServiceStub;
private final OrderServiceGrpc.OrderServiceStub orderServiceStub;
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private final DepotServiceGrpc.DepotServiceStub depotServiceStub;
/**
* Construct client for accessing ActiveTrader using the existing channel.
*/
TestClient(ManagedChannel channel) { (1)
this.channel = channel;
securityServiceBlockingStub = SecurityServiceGrpc.newBlockingStub(channel); (2)
securityServiceStub = SecurityServiceGrpc.newStub(channel); (3)
stockExchangeServiceBlockingStub = StockExchangeServiceGrpc.newBlockingStub(channel);
accountServiceBlockingStub = AccountServiceGrpc.newBlockingStub(channel);
accountServiceStub = AccountServiceGrpc.newStub(channel);
orderServiceStub = OrderServiceGrpc.newStub(channel);
orderServiceBlockingStub = OrderServiceGrpc.newBlockingStub(channel);
depotServiceStub = DepotServiceGrpc.newStub(channel);
accessServiceBlockingStub = AccessServiceGrpc.newBlockingStub(channel);
}
| 1 | Use managed channel from previous step |
| 2 | Initialize blocking stub |
| 3 | Initialize non blocking stub |
|
Warning
Be care that you use non blocking stub to subscribe for push events. It’s technically possible, but blocks program execution until server will stop send events. |
Functional programming
Objects in the GRPC world are immutable (or not changable). To create these objects are used object builders. They fill objects and build final immutable object for the execution. It looks like a chain of the functions calls.
1
2
3
4
5
6
7
8
9
10
11
12
AddOrderRequest request = AddOrderRequest.newBuilder() (1)
.setAccessToken(accessToken) (2)
.setAccountNumber("123467890")
.setSecurityWithStockexchange(securityWithStockExchange)
.setValidation(Validation.VALIDATE_ONLY)
.setAmount(1)
.setOrderModel(OrderModel.LIMIT)
.setLimit(1)
.setOrderType(OrderType.BUY)
.setCashQuotation(CashQuotation.KASSA)
.setValidityDate(Date.newBuilder().setDay(10).setMonth(10).setYear(2018).build())
.build(); (3)
| 1 | Create builder |
| 2 | Set objects parameters |
| 3 | Build final object |
|
Important
It’s necessary to fill only parameters that need for the function call. All other parameters should stay untouched or should have default values. |
Pull and push functions
There is two possibilites to call remote function.
Pull requests
The first one is using blocking service stub. In this case an operation blocks program execution until results are arrived.
1
2
3
4
5
6
private TradingAccounts getTradingAccounts() {
AccessTokenRequest request = AccessTokenRequest.newBuilder()
.setAccessToken(accessToken)
.build();
return accountServiceBlockingStub.getTradingAccounts(request);
}
Push requests
Other possibility is not to wait for the results, but listen for then asynchronically.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void getTradingAccountsAsync() {
AccessTokenRequest request = AccessTokenRequest.newBuilder()
.setAccessToken(accessToken)
.build();
accountServiceStub.getTradingAccounts(request, new StreamObserver<TradingAccounts>() { (1)
@Override
public void onNext(TradingAccounts tradingAccounts) {
System.out.println(tradingAccounts); (2)
}
@Override
public void onError(Throwable t) {
t.printStackTrace(); (3)
}
@Override
public void onCompleted() {
System.out.println("No results anymore"); (4)
}
});
}
| 1 | Subscribe for the results |
| 2 | Process results |
| 3 | Called by technical error |
| 4 | Called after processing end. No new result are comming anymore. |
The results are comming only once. The operation will be automatically completed.
Push subscriptions
In some cases server can sent more then one answer or streams the data. This case is simular t requests, but has some differences.
-
It can come more then one results answer back
-
Server can send "break" notification to the client if no data is exist anymore
-
Client can send "break" notification to the server if no data is need anymore. See ServerSubs
Services and functions
Access service
Access service provides functionality to validation / invalidation of the client.
| Function | Description |
|---|---|
LoginReply = Login(LoginRequest) |
Validates client by the TAPI and gets access data |
LogoutReply = Logout(LogoutRequest) |
Invalidates client by the TAPI and gets logout result |
Client validation
Client validation should be a first request after connection initalization. To validate client you have to set a secret that was set in the ActiveTrader configuration and process a login function. As result of this function returned session access token. This token is necessary to set to each request that will be send by TAPI.
1
2
3
4
5
6
7
8
9
10
11
12
private String login(String secret) {
LoginRequest loginRequest = LoginRequest.newBuilder()
.setSecret(secret)
.build();
LoginReply loginReply = accessServiceBlockingStub.login(loginRequest);
if (loginReply.getError()!=Error.getDefaultInstance()) {
System.err.println(loginReply.getError());
return "";
} else {
return loginReply.getAccessToken();
}
}
Client invalidation
After finishing of usage of the TAPI is necessary to invalidate session. That can be done with help of the logout function. .Example Java: Logout
private void logout() { if (accessToken!=null && !accessToken.isEmpty()) { LogoutRequest request = LogoutRequest.newBuilder() .setAccessToken(accessToken) .build(); accessServiceBlockingStub.logout(request); } }
Account service
Account service provides access to the trading accounts and gives possibility to access to the accounts data and transactions.
| Function | Description |
|---|---|
TradingAccounts = GetTradingAccounts(AccessTokenRequest) |
Gets trading accounts @return TradingAccounts List of trading accounts |
TradingAccountInformation ⇐ StreamTradingAccount(TradingAccountRequest) |
Subscribes one trading account for updates @param TradingAccount Trading account for push @stream TradingAccountInformation Specific information for subscribed account (balance, kredit line, etc.) |
TradingAccountTransactions ⇐ StreamTradingAccountTransactions(TradingAccountRequest) |
Subscribes one trading account for the transactions updates @param TradingAccount Trading account for push @stream TradingAccountInformation Transactions list for subscribed account |
To subscribe for the account and transactions changes you have to get trading accounts and subscribe each account with help of steam functions for data changes independently.
Get list of trading accounts
Many activites need information about an account data. Most important information is a trading account number. To get list of all avialable trading accounts you have to use Get Trading Accounts function.
1
2
3
4
5
6
7
8
9
10
private static final Empty EMPTY = Empty.getDefaultInstance();
private final AccountServiceGrpc.AccountServiceBlockingStub accountServiceBlockingStub;
private TradingAccounts getTradingAccounts() {
AccessTokenRequest request = AccessTokenRequest.newBuilder()
.setAccessToken(accessToken)
.build();
return accountServiceBlockingStub.getTradingAccounts(request);
}
|
Important
Not all accounts in the pro version of the ActiveTrader can be used for the trading functionality. Please refer to the TradingAccount and check for the access avialibility of the selected account (flag: tradable). |
|
Useful
Typical use case is to get this information once and keep it during one connection session. |
Stream account information changes
To get pushed trading account information is need to subscribe an account for the trading account stream.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void streamTradingAccountInformation() {
TradingAccounts tradingAccounts = getTradingAccounts(); (1)
for (int accountIndex = 0; accountIndex<tradingAccounts.getAccountsCount(); accountIndex++) {
TradingAccount account = tradingAccounts.getAccounts(accountIndex); (2)
TradingAccountRequest request = TradingAccountRequest.newBuilder()
.setAccessToken(accessToken)
.setTradingAccount(account)
.build();
TradingAccountInformationObserver observer = (3)
new TradingAccountInformationObserver(request, accountServiceStub);
accountObservers.put(account, observer);
}
}
| 1 | Get trading accounts |
| 2 | Iterate over each account |
| 3 | Subscribe account |
TradingAccountInformationObserver is the help class to encapsulate typical processing with the stream data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import com.consorsbank.module.tapi.grpc.AccountServiceGrpc.AccountServiceStub;
import com.consorsbank.module.tapi.grpc.account.TradingAccount;
import com.consorsbank.module.tapi.grpc.account.TradingAccountInformation;
import com.consorsbank.module.tapi.grpc.account.TradingAccountRequest;
import com.consorsbank.module.tapi.grpc.common.Error;
public class TradingAccountInformationObserver extends ServerSubscription<TradingAccount, TradingAccountInformation>{
private final AccountServiceStub orderServiceStub;
public TradingAccountInformationObserver(
TradingAccountRequest request, AccountServiceStub orderServiceStub) {
this.orderServiceStub = orderServiceStub;
this.orderServiceStub.streamTradingAccount(request, this); (1)
}
@Override
public void onCompleted() { (2)
System.out.println("Call completed!");
}
@Override
public void onNext(TradingAccountInformation reply) { (3)
Error error = reply.getError(); (4)
if (error==Error.getDefaultInstance()) {
System.out.printf("Async trading information: %s%n", reply);
} else {
System.out.printf("Error: %s%n", error);
}
}
}
| 1 | Subscribe for account information |
| 2 | Called on the completting subscription |
| 3 | Called on the account information change |
| 4 | Check for an error |
ServerSubscription contains functions to control streaming of the data. If, for example, you don’t need to recieve data from any subscription, you can unsubscribe it with help of close function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.ClientCallStreamObserver;
import io.grpc.stub.ClientResponseObserver;
public abstract class ServerSubscription<R, T> implements ClientResponseObserver<R, T>, Closeable {
private ClientCallStreamObserver<R> observer;
/**
* This function is called during subscription initialization.
* observer will created by GRPC engine and can be used for
* data flow control.
*/
@Override
public void beforeStart(ClientCallStreamObserver<R> observer) {
this.observer = observer; (1)
}
/**
* Call this function to unsubscribe from server
*/
@Override
public void close() {
observer.cancel("Fin", null); (2)
}
// ...
}
| 1 | Store client observer by initialization |
| 2 | Stop listening events (unsubscribe from stream) |
Stream account transactions changes
To get pushed trading account transactions list is need to subscribe account for trading account transactions stream.
1
2
3
4
5
6
7
8
9
10
11
12
13
private void streamTradingAccountTransactions() {
TradingAccounts tradingAccounts = getTradingAccounts(); (1)
for (int accountIndex = 0; accountIndex<tradingAccounts.getAccountsCount(); accountIndex++) {
TradingAccount account = tradingAccounts.getAccounts(accountIndex); (2)
TradingAccountRequest request = TradingAccountRequest.newBuilder()
.setAccessToken(accessToken)
.setTradingAccount(account)
.build();
TradingAccountTransactionsObserver observer = (3)
new TradingAccountTransactionsObserver(request, accountServiceStub);
accountTransactionsObservers.put(account, observer);
}
}
| 1 | Get trading accounts |
| 2 | Iterate over each account |
| 3 | Subscribe account |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import com.consorsbank.module.tapi.grpc.AccountServiceGrpc.AccountServiceStub;
import com.consorsbank.module.tapi.grpc.account.TradingAccount;
import com.consorsbank.module.tapi.grpc.account.TradingAccountRequest;
import com.consorsbank.module.tapi.grpc.account.TradingAccountTransactions;
import com.consorsbank.module.tapi.grpc.account.TradingAccountTransactions.Transaction;
import com.consorsbank.module.tapi.grpc.common.Error;
public class TradingAccountTransactionsObserver extends ServerSubscription<TradingAccount, TradingAccountTransactions>{
private final AccountServiceStub orderServiceStub;
public TradingAccountTransactionsObserver(
TradingAccountRequest request, AccountServiceStub orderServiceStub) {
this.orderServiceStub = orderServiceStub;
this.orderServiceStub.streamTradingAccountTransactions(request, this); (1)
}
@Override
public void onCompleted() { (2)
System.out.println("Call completed!");
}
@Override
public void onNext(TradingAccountTransactions transactions) { (3)
Error error = transactions.getError(); (4)
if (error==Error.getDefaultInstance()) {
System.out.printf("Async trading transactions: %s%n", transactions);
TradingAccount account = transactions.getAccount();
List<Transaction> transactionsList = transactions.getTransactionsList();
// ...
} else {
System.out.printf("Error: %s%n", error);
}
}
}
| 1 | Subscribe for the account information |
| 2 | Called on the completting subscription |
| 3 | Called on the account transactions change |
| 4 | Check for an error |
Stock exchange service
StockExchange service provides access to the stock exchanges.
| Function | Description |
|---|---|
StockExchangeDescriptions = GetStockExchanges(AccessTokenRequest) |
Gets predefined stockexchages @return StockExchangeDescriptions list of stock exchange informations |
StockExchangeDescription = GetStockExchange(StockExchangeRequest) |
Gets specific stock exchange @param StockExchange Requested stock exchange @return StockExchangeDescription Stock exchange information |
Get information about all stock exchanges
TAPI has list of predefined stock exchanges that can be fetched directly. Each stock exchange has id and optional issuer. Some stock exchanges have identical id’s, but different issuers. For examples:
| id | issuer | shortcut id | stock exchange name |
|---|---|---|---|
ETR |
ETR |
Xetra |
|
OTC |
BAAD |
BAA |
Baada bank on OTC |
OTC |
7649 |
LUS |
Lang und Schwarz |
OTC |
7004 |
Commerzbank |
|
OTC |
OTC |
Any issuer on OTC |
|
Useful
It’s possible to use shortcut id, if it exists, to access to the same stock exchange. For example stock exchange ("OTC", "BAAD") equivalent to the stock exchange ("BAA","") |
These stock exchanges can be requested with help of Get Stock Exchanges function. As a result will delivered stock exchanges with names.
1
2
3
4
5
6
7
8
9
10
private static final Empty EMPTY = Empty.getDefaultInstance();
private final StockExchangeServiceGrpc.StockExchangeServiceBlockingStub stockExchangeServiceBlockingStub;
private StockExchangeDescriptions getStockExchanges() {
AccessTokenRequest request = AccessTokenRequest.newBuilder()
.setAccessToken(accessToken)
.build();
return stockExchangeServiceBlockingStub.getStockExchanges(request);
}
|
Useful
This information can be stored and reused in the user application. |
Get information about specific stock exchange
It’s also possible to get information about one specific stock exchange. Next example shows how to request stock exchange information about Baada issuer on the OTC:
1
2
3
4
5
6
7
8
9
10
11
12
private StockExchangeDescription getBaadaStockExchangeInformation() {
StockExchange stockExchange = StockExchange.newBuilder()
.setId("OTC")
.setIssuer("BAAD")
.build(); (1)
StockExchangeRequest request = StockExchangeRequest.newBuilder()
.setAccessToken(accessToken)
.setStockExchange(stockExchange)
.build(); (2)
return stockExchangeServiceBlockingStub.getStockExchange(request); (3)
}
| 1 | Prepare Baada on OTC stock exchange |
| 2 | Build request |
| 3 | Request information about stock exchange |
Depot service
With help of the depot service is possible to stream information about depot entries. Depot service has next functions:
Stream depot changes
| Function | Description |
|---|---|
DepotEntries ⇐ StreamDepot(TradingAccountRequest) |
Subscribes one trading account for the depot data updates @param TradingAccount Trading account for push @stream DepotEntries depot entries linked to the account |
Empty = UpdateDepot(TradingAccountRequest) |
Initiates depot update action. All changes come by the StreamDepot subscription. This function doesn’t wait for the action result. @param TradingAccount Trading account for update |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private final DepotServiceGrpc.DepotServiceStub depotServiceStub;
private void streamDepotData() {
TradingAccounts tradingAccounts = getTradingAccounts(); (1)
for (int accountIndex = 0; accountIndex<tradingAccounts.getAccountsCount(); accountIndex++) {
TradingAccount account = tradingAccounts.getAccounts(accountIndex);
TradingAccountRequest request = TradingAccountRequest.newBuilder()
.setAccessToken(accessToken)
.setTradingAccount(account)
.build();
DepotObserver depotObserver = new DepotObserver(request, depotServiceStub); (2)
depotObservers.put(account, depotObserver);
}
}
| 1 | Get trading accounts |
| 2 | Greate depot observer for each account |
Update events are delivered on each depot entry change and contain information about whole depot.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DepotObserver extends ServerSubscription<TradingAccountRequest, DepotEntries>{
private final DepotServiceStub serviceStub;
public DepotObserver(TradingAccountRequest request, DepotServiceStub depotServiceStub) {
this.serviceStub = depotServiceStub;
this.serviceStub.streamDepot(request, this); (1)
}
@Override
public void onCompleted() { (2)
System.out.println("Call completed!");
}
@Override
public void onNext(DepotEntries depotEntries) { (3)
Error error = depotEntries.getError(); (4)
if (error==Error.getDefaultInstance()) {
System.out.printf("Async depot: %s%n", depotEntries);
TradingAccount account = depotEntries.getAccount();
List<DepotEntry> entriesList = depotEntries.getEntriesList();
// ...
} else {
System.out.printf("Error: %s%n", error);
}
}
}
| 1 | Subscribe for the depot data |
| 2 | Called on the completing subscription |
| 3 | Called on the depot entries change |
| 4 | Check for an error |
Update depot
Sometime is necessary to update depot manually. To initiate this update you have to call UpdateDepot function. This function takes trading account as input parameter and doesn’t deliver any results. It’s also don’t wait for the results. All changes are delivered directly to the depot listeners in the background.
|
Warning
This function used for the compatibility proposals and can be removed in the future versions of the TAPI. |
Security service
Securities access
All securities can be accessed with help of security codes. Typical trading securities codes are WKN and ISIN. TAPI is able to operate with additional security code types:
| Security code type | Tradable | Description |
|---|---|---|
WKN |
Yes |
WKN |
ISIN |
Yes |
ISIN |
ID_NOTATION |
No |
FactSet id notation |
ID_OSI |
No |
FactSet id osi |
ID_INSTRUMENT |
No |
FactSet id instrument |
MNEMONIC |
No |
German short id |
MEMONIC_US |
No |
US short id (only for us instruments) |
Security code can be created with help of next code.
1
2
3
4
5
6
public static SecurityCode getSecurityCode(String code, SecurityCodeType codeType) {
return SecurityCode.newBuilder() (1)
.setCode(code) (2)
.setCodeType(codeType==null ? SecurityCodeType.NO_CODE_TYPE : codeType) (3)
.build(); (4)
}
| 1 | Create builder for SecurityCode object |
| 2 | Set security code |
| 3 | Set security code type (WKN, ISIN, . . .) |
| 4 | Build immutable SecurityCode object |
|
Important
In some cases TAPI can guess security code type by input security code value. In this case the security code type should be set to NO_CODE_TYPE value. Please care that’s not guaranty right detection of the security code. The good practice is to use security code type by the building of the security code object. |
Security service contains next functions:
| Function | Description |
|---|---|
SecurityInfoReply = GetSecurityInfo(SecurityInfoRequest) |
Gets security information about security @param SecurityInfoRequest Request object with interested security @return SecurityInfoReply Complete information about security |
SecurityMarketDataReply ⇐ StreamMarketData(SecurityMarketDataRequest) |
Subscribes security with stock exchange for market data updates @param SecurityMarketDataRequest Market data request with interested security and stock exchange @stream SecurityMarketDataReply Reply with all market data values |
SecurityOrderBookReply ⇐ StreamOrderBook(SecurityOrderBookRequest) |
Subscribes security with stock exchange for orderbook updates @param SecurityOrderBookRequest Orderbook data request with interested security and stock exchange @stream SecurityOrderBookReply Reply with all orderbook values |
CurrencyRateReply ⇐ StreamCurrencyRate(CurrencyRateRequest) |
Subscribes for currency rate from one currency to another currency. @param SecurityOrderBookRequest currency rate request with interested currencies from/to @stream CurrencyRateReply reply with currency rate |
SecurityPriceHistoryReply = GetSecurityPriceHistory(SecurityPriceHistoryRequest) |
Requests history data for one security on one stockexchange in intraday or historical format @param SecurityPriceHistoryRequest Data with security, stockexchange, how many days and resolution @return SecurityPriceHistoryReply List of the historical quotes or an error |
Get security information
Security information can be requested with help of GetSecurityInfo function. As a result will delivered security name, class, codes and stock exchanges with trading possibilites. This information can be used by the ordering. It also contains data about tradabity on the different markets and by different issuers. The flags LimitToken with values QUOTE_ONLY and LIMIT_AND_QUOTE show if for the security is possible to use quote buy and sell on the selected market by the selected issuer. For more information please see GetQuote and AcceptQuote functions.
1
2
3
4
5
6
7
8
9
10
11
private final SecurityServiceGrpc.SecurityServiceBlockingStub securityServiceBlockingStub;
private SecurityInfoReply requestSecurityInfo(String code, SecurityCodeType securityCodeType) {
SecurityCode securityCode = TestUtils.getSecurityCode(code, securityCodeType); (1)
SecurityInfoRequest request = SecurityInfoRequest.newBuilder() (2)
.setAccessToken(accessToken)
.setSecurityCode(securityCode) (3)
.build(); (4)
SecurityInfoReply response = securityServiceBlockingStub.getSecurityInfo(request); (5)
return response;
}
| 1 | Create security code object |
| 2 | Create builder for SecurityinfoRequest object |
| 3 | Set security code |
| 4 | Build immutable SecurityinfoRequest object |
| 5 | Request security information |
Stream market data information
To get pushed market data (push courses) is need to subscribe security and stock exchange for this information with help of StreamMarketData function. SecurityMarketDataReply contains all values, which were changed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private final SecurityServiceGrpc.SecurityServiceStub securityServiceStub;
private MarketDataDataObserver streamMarketData(String code,
SecurityCodeType securityCodeType, String stockExchangeId, String currency) {
SecurityWithStockExchange securityWithStockExchange = (1)
TestUtils.getSecurityWithStockExchange(code, securityCodeType, stockExchangeId, null);
SecurityMarketDataRequest request = SecurityMarketDataRequest.newBuilder()
.setAccessToken(accessToken)
.setSecurityWithStockexchange(securityWithStockExchange) (2)
.setCurrency(currency!=null ? currency : "")
.build();
MarketDataDataObserver marketDataDataObserver = (3)
new MarketDataDataObserver(request, securityServiceStub);
String key = code+"|"+securityCodeType+"|"+stockExchangeId+"|"+currency;
marketDataObservers.put(key, marketDataDataObserver);
return marketDataDataObserver;
}
| 1 | Prepare security with stock exchange |
| 2 | Prepare request |
| 3 | Greate MarketDataDataObserver to subscribe market data information |
Update events deliver changed market data values.
To subscribe for the market data information it is necessary to create SecurityWithStockExchange object.
1
2
3
4
5
6
7
8
public static SecurityWithStockExchange getSecurityWithStockExchange(
SecurityCode securityCode, StockExchange stockExchange) {
return SecurityWithStockExchange.newBuilder() (1)
.setSecurityCode(securityCode) (2)
.setStockExchange(stockExchange) (3)
.build(); (4)
}
| 1 | Create builder for SecurityWithStockExchange object |
| 2 | Set security code |
| 3 | Set stock exchange |
| 4 | Build immutable SecurityWithStockExchange object |
You have to prepare StockExchange object.
1
2
3
4
5
6
7
8
public static StockExchange getStockExchange(String stockExchangeId, String issuer) {
Builder stockBuilder = StockExchange.newBuilder(); (1)
if (issuer!=null) {
stockBuilder.setIssuer(issuer); (2)
}
return stockBuilder.setId(stockExchangeId) (3)
.build(); (4)
}
| 1 | Create builder for StockExchange object |
| 2 | Set issuer |
| 3 | Set stock exchange id |
| 4 | Build immutable StockExchange object |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MarketDataDataObserver extends ServerSubscription<SecurityMarketDataRequest, SecurityMarketDataReply> {
private final SecurityServiceStub securityServiceStub;
public MarketDataDataObserver(SecurityMarketDataRequest request,
SecurityServiceStub securityServiceStub) {
this.securityServiceStub = securityServiceStub;
securityServiceStub.streamMarketData(request, this); (1)
}
@Override
public void onCompleted() {
System.out.println("Call completed!"); (2)
}
@Override
public void onNext(SecurityMarketDataReply response) {
Error error = response.getError();
if (error==Error.getDefaultInstance()) { (3)
System.out.printf("Async client onNext: %s%n", response);
double lastPrice = response.getLastPrice();
Timestamp lastDateTime = response.getLastDateTime();
// ...
} else {
System.out.printf("Error: %s%n", error);
}
}
}
| 1 | Subscribe for the market data |
| 2 | Called of complete subscription |
| 3 | Process madret data events |
Stream orderbook data
To get pushed orderbook data (second level push courses) is need to subscribe security and stockexchange for this information with help of StreamOrderBook function. SecurityOrderBookReply contains actual orderbook values. To create SecurityOrderBookRequest is need to create SecurityWithStockExchange object first. Currently order book data supported only on Xetra stock exchange.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private final SecurityServiceGrpc.SecurityServiceStub securityServiceStub;
private OrderBookDataObserver streamOrderBook(String code,
SecurityCodeType securityCodeType, String stockExchangeId, String currency) {
SecurityWithStockExchange securityWithStockExchange = (1)
TestUtils.getSecurityWithStockExchange(code, securityCodeType, stockExchangeId, null);
SecurityOrderBookRequest request = SecurityOrderBookRequest.newBuilder()
.setAccessToken(accessToken)
.setSecurityWithStockexchange(securityWithStockExchange)
.setCurrency(currency==null ? "" : currency)
.build(); (2)
OrderBookDataObserver orderBookDataObserver = (3)
new OrderBookDataObserver(request, securityServiceStub);
String key = code+"|"+securityCodeType+"|"+stockExchangeId+"|"+currency;
orderBookObservers.put(key, orderBookDataObserver);
return orderBookDataObserver;
}
| 1 | Prepare security with stock exchange |
| 2 | Prepare request |
| 3 | Greate OrderBookData observer to subscribe orderbook information |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class OrderBookDataObserver extends ServerSubscription<SecurityOrderBookRequest, SecurityOrderBookReply> {
private final SecurityServiceStub securityServiceStub;
public OrderBookDataObserver(SecurityOrderBookRequest request,
SecurityServiceStub securityServiceStub) {
this.securityServiceStub = securityServiceStub;
securityServiceStub.streamOrderBook(request, this); (1)
}
@Override
public void onCompleted() {
System.out.println("Call completed!"); (2)
}
@Override
public void onNext(SecurityOrderBookReply response) {
Error error = response.getError();
if (error==Error.getDefaultInstance()) {
System.out.printf("Async client onNext: %s%n", response); (3)
List<OrderBookEntry> orderBookEntriesList = response.getOrderBookEntriesList();
for (OrderBookEntry orderBookEntry : orderBookEntriesList) {
double askPrice = orderBookEntry.getAskPrice();
double askVolume = orderBookEntry.getAskVolume();
}
// ...
} else {
System.out.printf("Error: %s%n", error);
}
}
}
| 1 | Subscribe for orderbook data |
| 2 | Called on complete subscription |
| 3 | Process order book events |
Stream currency rate
It is possible to get pushed currency rate from one currency to other. This information can be used for the realtime convertation of the money values.
|
Important
For the market data quotes / order books it is possible to define target currency. It this case the convertation will be processed automatically. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private final SecurityServiceGrpc.SecurityServiceStub securityServiceStub;
private CurrencyRateDataObserver streamCurrencyRate(String currencyFrom, String currencyTo) {
CurrencyRateRequest request = CurrencyRateRequest.newBuilder()
.setAccessToken(accessToken)
.setCurrencyFrom(currencyFrom)
.setCurrencyTo(currencyTo)
.build(); (1)
CurrencyRateDataObserver currencyRateDataObserver = (2)
new CurrencyRateDataObserver(request, securityServiceStub);
String key = currencyFrom+"|"+currencyTo;
currencyObservers.put(key, currencyRateDataObserver);
return currencyRateDataObserver;
}
| 1 | Greate request |
| 2 | Greate CurrencyRateData observer to subscribe currency rate |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class CurrencyRateDataObserver extends ServerSubscription<CurrencyRateRequest, CurrencyRateReply> {
private final SecurityServiceStub securityServiceStub;
public CurrencyRateDataObserver(CurrencyRateRequest request,
SecurityServiceStub securityServiceStub) {
this.securityServiceStub = securityServiceStub;
securityServiceStub.streamCurrencyRate(request, this); (1)
}
@Override
public void onCompleted() {
System.out.println("Call completed!"); (2)
}
@Override
public void onNext(CurrencyRateReply response) {
Error error = response.getError();
if (error==Error.getDefaultInstance()) {
System.out.printf("Async client onNext: %s%n", response);
double currencyRate = response.getCurrencyRate(); (3)
// ...
} else {
System.out.printf("Error: %s%n", error);
}
}
}
| 1 | Subscribe for currency rate |
| 2 | Called on complite subscription |
| 3 | Process currency rate events |
Get security historic data
Security historic data can be requested with help of getSecurityPriceHistory() function. As a result will delivered security with stock exchange, currency, historic data list. The parameter days defines how many trading day will be requested. For intraday types of the time resolution this value should be 15 or less. Be careful the amount of the data can be very big, especialy for intraday data with tick resolution.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private final SecurityServiceGrpc.SecurityServiceBlockingStub securityServiceBlockingStub;
private SecurityPriceHistoryReply getSecurityPriceHistory(
String code, SecurityCodeType securityCodeType, String stockExchangeId,
int days, TimeResolution resolution) {
SecurityWithStockExchange securityWithStockExchange = (1)
TestUtils.getSecurityWithStockExchange(code, securityCodeType, stockExchangeId, null);
SecurityPriceHistoryRequest request = SecurityPriceHistoryRequest.newBuilder() (2)
.setAccessToken(accessToken)
.setSecurityWithStockexchange(securityWithStockExchange) (3)
.setDays(days) (4)
.setTimeResolution(resolution) (5)
.build(); (6)
SecurityPriceHistoryReply response =
securityServiceBlockingStub.getSecurityPriceHistory(request); (7)
return response;
}
| 1 | Create security with stock exchange object |
| 2 | Create builder for SecurityPriceHistoryRequest object |
| 3 | Set security with stock exchange |
| 4 | Set days number |
| 5 | Set time resolution (tick, minute, etc) |
| 6 | Build immutable SecurityPriceHistoryRequest object |
| 7 | Request historic data |
|
Important
Last example will block program execution until the result is returned. Sometimes to avoid timeouts by the listening it’s better to use non blocking calls. |
Order service
With help of the order service is possible to execute, change, activate, deactivate or cancel orders. It’s also allow to listen for the orders and to control them asyncronically.
Order types and parameters
TAPI allowes to execute different order types on the stock exchanges with different parameters. Next tables shows what parameters are necessary (x) and optional (o) depends from selected stock exchange and order model. The full list of order possibilites is delivered by the GetSecurityInformation function.
| Parameter \ Order model | Market | Limit | StopMarket | StopLimit | OneCancelsOtherMarket | OneCancelsOtherLimit | TrailingStopMarket | TrailingStopLimit |
|---|---|---|---|---|---|---|---|---|
account_number |
x |
x |
x |
x |
x |
x |
x |
x |
security_with_stockexchange |
x |
x |
x |
x |
x |
x |
x |
x |
order_type |
x |
x |
x |
x |
x |
x |
x |
x |
amount |
x |
x |
x |
x |
x |
x |
x |
x |
order_supplement |
o, 1) |
o, 1) |
||||||
validity_date |
x |
x |
x |
x |
x |
x |
x |
x |
limit |
x |
x |
x |
|||||
stop |
x |
x |
x |
x |
x |
x |
||
stop_limit |
x |
x |
||||||
trailing_distance |
x |
x |
||||||
trailing_notation |
x |
x |
||||||
trailing_limit_tolerance |
x, 2) |
|||||||
dripping_quantity |
o, 3) |
o, 3) |
||||||
position_id |
o, 4) |
o, 4) |
o, 4) |
o, 4) |
o, 4) |
o, 4) |
o, 4) |
o, 4) |
validation |
o ,5) |
o ,5) |
o ,5) |
o ,5) |
o ,5) |
o ,5) |
o ,5) |
o ,5) |
cash_quotation |
o, 6) |
o, 6) |
o, 6) |
o, 6) |
o, 6) |
o, 6) |
o, 6) |
o, 6) |
risk_class_override |
o |
o |
o |
o |
o |
o |
o |
o |
target_market_override |
o |
o |
o |
o |
o |
o |
o |
o |
tax_nontransparent_override |
o |
o |
o |
o |
o |
o |
o |
o |
accept_additional_fees |
o |
o |
o |
o |
o |
o |
o |
o |
closed_realestate_fond_override |
o |
o |
o |
o |
o |
o |
o |
o |
| 1 | Stock exchange: ETR only, values: IMMIDIATE_OR_CANCEL, FILL_OR_KILL, ICEBERG |
| 2 | Stock exchange: TRG only |
| 3 | Stock exchange: ETR only, when order_supplement equals ICEBERG, pro only |
| 4 | Position id is optional field by the order action with existing depot position |
| 5 | Default value: WITHOUT_VALIDATION. Order is routed directly to market |
| 6 | Cash quotation: |
| Stock exchange | NOTHING | KASSA | AUCTION | OPENING | INTRADAY | CLOSING |
|---|---|---|---|---|---|---|
ETR |
x |
x |
x |
x |
x |
x |
German |
x |
x |
||||
Other |
x |
The full list of the order service functions can be checked in the next list. Some functionality avialable only in pro version of the ActiveTrader.
|
Important
To execute new order is need at least to fill all madatory fields. See x values in the each column for selected order model. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SecurityWithStockExchange securityWithStockExchange = TestUtils.getSecurityWithStockExchange("710000", SecurityCodeType.WKN, "ETR", null);
//
AddOrderRequest addRequest = AddOrderRequest.newBuilder() (1)
.setOrderModel(OrderModel.ONE_CANCELS_OTHER_MARKET) (2)
.setAccountNumber(account.getAccountNumber())
.setSecurityWithStockexchange(securityWithStockExchange)
.setAmount(1)
.setValidation(Validation.VALIDATE_ONLY)
.setLimit(39)
.setStop(40)
.setOrderType(OrderType.BUY)
.setValidityDate(TestUtils.getDate(LocalDate.now())) // today
.build();
OrderReply addReply = getOrdersBlockingStub().addOrder(addRequest); (3)
| 1 | Fill mandatory parameters |
| 2 | OneCancelOtherMarket order and it’s parameters |
| 3 | Process order |
Stream orders
To get information about current orders ist need to subscribe for this information with help of StreamOrders function. All order changes will come asynchronically as a list of the all avialable orders.
|
Useful
An amount of the updated orders can be configured in the ActiveTrader general settings. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private final OrderServiceGrpc.OrderServiceStub orderServiceStub;
private void streamOrders() {
TradingAccounts tradingAccounts = getTradingAccounts(); (1)
for (int accountIndex = 0; accountIndex<tradingAccounts.getAccountsCount(); accountIndex++) {
TradingAccount account = tradingAccounts.getAccounts(accountIndex); (2)
TradingAccountRequest request = TradingAccountRequest.newBuilder()
.setAccessToken(accessToken)
.setTradingAccount(account)
.build();
OrdersObserver ordersObserver = new OrdersObserver(request, orderServiceStub); (3)
ordersObservers.put(account, ordersObserver);
}
}
| 1 | Get trading accounts |
| 2 | Iterate over each account |
| 3 | Subscribe account |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import com.consorsbank.module.tapi.grpc.OrderServiceGrpc.OrderServiceStub;
import com.consorsbank.module.tapi.grpc.account.TradingAccount;
import com.consorsbank.module.tapi.grpc.account.TradingAccountRequest;
import com.consorsbank.module.tapi.grpc.common.Error;
import com.consorsbank.module.tapi.grpc.order.Order;
import com.consorsbank.module.tapi.grpc.order.Orders;
public class OrdersObserver extends ServerSubscription<TradingAccount, Orders>{
private final OrderServiceStub orderServiceStub;
public OrdersObserver(TradingAccountRequest request, OrderServiceStub orderServiceStub) {
this.orderServiceStub = orderServiceStub;
this.orderServiceStub.streamOrders(request, this); (1)
}
@Override
public void onCompleted() { (2)
System.out.println("Call completed!");
}
@Override
public void onNext(Orders orders) { (3)
Error error = orders.getError(); (4)
if (error==Error.getDefaultInstance()) {
System.out.printf("Async orders: %s%n", orders);
TradingAccount account = orders.getAccount();
List<Order> ordersList = orders.getOrdersList();
// ...
} else {
System.out.printf("Error: %s%n", error);
}
}
}
| 1 | Subscribe for the order data |
| 2 | Called on the completing subscription |
| 3 | Called on the depot entries change |
| 4 | Check for an error |
|
Important
In the pro version of the ActiveTrader order number value can be changed (for example after activation / deactivation of the order). To match saved in the client application orders with the orders from update is need to use unique_id field from the Order object. |
Update orders
Sometime is necessary to update orders manually. To initiate this update you have to call UpdateOrders function. This function takes trading account as input parameter and doesn’t deliver any results. It’s also don’t wait for the results. All changes are delivered directly to the orders listeners in the background.
|
Warning
This function used for the compatibility proposals and can be removed in the future versions of the TAPI. |
Get securities quotes
Before to execute order add action is often necessary to get actual quote information for the selected security. This information can be subscribed in the security service or requested in the order service. It’s not a matter where this information is requested for the normal order add action, but it’s important in case if you want to process accept quote on the short term market. In this case is necessary to use get quote function from order service.
|
Important
Please call get quote function before to call of the accept order action. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void requestQuotesDirect(String code, SecurityCodeType securityCodeType) {
QuoteRequest quoteRequest = QuoteRequest.newBuilder()
.setAccessToken(accessToken)
.setOrderType(OrderType.BUY) (1)
.setSecurityCode(TestUtils.getSecurityCode(code, securityCodeType)) (2)
.setAmount(10) (3)
.addStockExchanges(TestUtils.getStockExchange("ETR", null)) (4)
.addStockExchanges(TestUtils.getStockExchange("OTC", null))
.addStockExchanges(TestUtils.getStockExchange("TRG", null))
.build();
QuoteReply quoteReply = orderServiceBlockingStub.getQuote(quoteRequest); (5)
if (quoteReply.getError()!=Error.getDefaultInstance()) {
List<QuoteEntry> priceEntriesList = quoteReply.getPriceEntriesList(); (6)
for (QuoteEntry quoteEntry : priceEntriesList) {
if (quoteEntry.getError()!=Error.getDefaultInstance()) {
// ...
}
}
}
}
| 1 | Set order type |
| 2 | Set security code |
| 3 | Set amount for the ordering |
| 4 | Set requestes stock exchanges |
| 5 | Request quotes with help of the blocking stub |
| 6 | Process results |
Other difference between quotes from the security service and order service is that it’s depended from user rights. An order service can have limited amount of the requests for the long terms stockexchanges. You can request data more then from one stock exchange for one security at once. In this case function returns all results for all requested stock exchanges after processing of all data for each stock exchange. That can follow to the timeouts by the functions calls. You can use asychronical requests if to don’t have timeouts is important. It’s also possible to process many get quote requests in parallel and pack to each request only one stockexchange. The results from the requests can be processed in background.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
private void requestQuotesAsynchronically(String code, SecurityCodeType securityCodeType) {
final StreamObserver<QuoteReply> quotesObserver = new StreamObserver<QuoteReply>() { (1)
@Override
public void onNext(QuoteReply quoteReply) {
System.err.println(quoteReply); (2)
if (quoteReply.getError()!=Error.getDefaultInstance()) {
List<QuoteEntry> priceEntriesList = quoteReply.getPriceEntriesList();
// priceEntriesList will contain only one entry
for (QuoteEntry quoteEntry : priceEntriesList) {
StockExchange stockExchange = quoteEntry.getStockExchange();
if (quoteEntry.getError()!=Error.getDefaultInstance()) {
// ...
}
}
}
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
}
@Override
public void onCompleted() {}
};
final SecurityCode securityCode = TestUtils.getSecurityCode(code, securityCodeType); (3)
final StockExchange[] stockexchanges = { (4)
TestUtils.getStockExchange("ETR", null),
TestUtils.getStockExchange("OTC", null),
TestUtils.getStockExchange("TRG", null),
};
// Request data
for (StockExchange stockExchange : stockexchanges) {
QuoteRequest quoteRequest = QuoteRequest.newBuilder() (5)
.setAccessToken(accessToken)
.setOrderType(OrderType.BUY)
.setSecurityCode(securityCode)
.setAmount(10)
.addStockExchanges(stockExchange)
.build();
orderServiceStub.getQuote(quoteRequest, quotesObserver);
}
// ...
}
| 1 | Prepare listener |
| 2 | Process results in the background |
| 3 | Prepare security code |
| 4 | Prepare stock exchanges |
| 5 | Request quotes with help of the non blocking stub |
Accept quote
To place an order on the short term market is necessary to request quote first. If QuoteEntry will contain filled quote_reference field then it’s possible to place order with help of accept quote function to the short term market. Otherwise accept quote is not possible. By the calling of the accept quote function you have to use same parameters as you used for the get quote. Otherwise the request parameters will be denied and the action will be finished with an error.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void acceptQuote() {
QuoteRequest quoteRequest = QuoteRequest.newBuilder() (1)
.setAccessToken(accessToken)
.setOrderType(OrderType.BUY)
.setSecurityCode(TestUtils.getSecurityCode("710000", SecurityCodeType.WKN))
.setAmount(10)
.addStockExchanges(TestUtils.getStockExchange("OTC", null))
.build();
PerformanceCounter pcGetQuote = new PerformanceCounter("GetQuote");
QuoteReply quoteReply = orderServiceBlockingStub.getQuote(quoteRequest); (2)
pcGetQuote.print();
if (quoteReply.getError()==Error.getDefaultInstance()) {
QuoteEntry quoteEntry = quoteReply.getPriceEntries(0); (3)
if (quoteEntry.getError()==Error.getDefaultInstance() &&
!quoteEntry.getQuoteReference().isEmpty()) { (4)
SecurityWithStockExchange securityWithStockExchange = (5)
TestUtils.getSecurityWithStockExchange(
quoteReply.getSecurityCode(), quoteEntry.getStockExchange());
AcceptQuoteRequest acceptQuoteRequest = AcceptQuoteRequest.newBuilder() (6)
.setAccessToken(accessToken)
.setOrderType(OrderType.BUY)
// .setAccountNumber(accountNumber)
.setSecurityWithStockexchange(securityWithStockExchange)
.setAmount(10)
.setValidation(Validation.VALIDATE_ONLY) (7)
.setLimit(quoteEntry.getBuyPrice())
.setQuoteReference(quoteEntry.getQuoteReference()) (8)
.build();
OrderReply acceptQuote = orderServiceBlockingStub.acceptQuote(acceptQuoteRequest); (9)
System.err.println(acceptQuote);
}
}
}
| 1 | Prepare get quote request |
| 2 | Call get quote function |
| 3 | Get recieved quotes (it should be only one quote, because we requested data for one stock exchange) |
| 4 | Check if we have quote reference |
| 5 | Prepare security with stock exchange object |
| 6 | Preapare accept quote request |
| 7 | Set validation flag |
| 8 | Set to the request quote reference |
| 9 | Call accept quote function and wait for the result |
|
Warning
By default validation parameter equals WITHOUT_VALIDATION and accept quote request will directly routed to the market. If you want only check a validity of the request, then you need to set validation parameter to VALIDATE_ONLY. An order will validated by the backend system, but will not be routed to the market. It’s very useful for the test goals. Order number in the reply in this case is undefined. |
Add order
To put new order to the long term marken is necessary to use AddOrder function. This function takes AddOrderRequest as an input parameter and returns OrderReply as a result. Typically this function is called with blocked stub, but it can also used with non blocking stub if more then one order need to executed in parallel.
The possible parameter combinations can be fetched from security information reply. There are defined order possibilities for defined markets.
Pro version of the ActiveTrader allowes to use additional flag inactive. If this flag set to the value true then order is placed to the system, but isn’t routed to the market. With the help of ActivateOrder function an order can be activated.
|
Important
It’s important to fill only parameters that need for the order execution |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private OrderReply addOrder() {
SecurityCode securityCode = TestUtils.getSecurityCode("710000", SecurityCodeType.WKN); (1)
StockExchange stockExchange = TestUtils.getStockExchange("ETR", null); (2)
SecurityWithStockExchange securityWithStockExchange =
TestUtils.getSecurityWithStockExchange(securityCode, stockExchange); (3)
AddOrderRequest request = AddOrderRequest.newBuilder() (4)
.setAccessToken(accessToken)
.setAccountNumber("123456789") (5)
.setSecurityWithStockexchange(securityWithStockExchange)
.setValidation(Validation.VALIDATE_ONLY) (6)
.setAmount(1)
.setOrderModel(OrderModel.LIMIT) (7)
.setLimit(1)
.setOrderType(OrderType.BUY) (8)
.setCashQuotation(CashQuotation.KASSA)
.setValidityDate(TestUtils.getDate(GregorianCalendar.getInstance()))
.build();
OrderReply addOrderReply = orderServiceBlockingStub.addOrder(request); (9)
System.err.println(addOrderReply);
return addOrderReply;
}
| 1 | Prepare security code |
| 2 | Prepare stock exchange |
| 3 | Prepare security with stock exchange |
| 4 | Prepare request |
| 5 | Set trading account |
| 6 | Set validation flag |
| 7 | Set order limit |
| 8 | Set order type |
| 9 | Process order add |
|
Warning
By default validation parameter equals WITHOUT_VALIDATION and accept quote request will directly routed to the market. If you want only check a validity of the request, then you need to set validation parameter to VALIDATE_ONLY. An order will validated by the backend system, but will not be routed to the market. It’s very useful for the test goals. Order number in the reply in this case is undefined. |
Change order
To change order is necessary to have order number of existing order and an account with this order linked to. The order can be changed if the status of the orders allowes that and new state is allowed by the markt.
|
Useful
Sometimes can happens that order is changed / executed on the market, but status information is not delivered into the application. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private void changeOrder(Order order, TradingAccount account) {
if (order!=null) {
String orderNumber = order.getOrderNumber();
if (orderNumber!=null && !orderNumber.isEmpty()) {
ChangeOrderRequest changeOrderRequest = ChangeOrderRequest.newBuilder()
.setAccessToken(accessToken)
.setAccountNumber(account.getAccountNumber()) (1)
.setOrderNumber(order.getOrderNumber()) (2)
.setValidation(Validation.VALIDATE_ONLY) (3)
.setOrderModel(OrderModel.LIMIT) (4)
.setLimit(2)
.build();
OrderReply changeOrderReply = (5)
orderServiceBlockingStub.changeOrder(changeOrderRequest);
System.out.println(changeOrderReply);
}
}
}
| 1 | Set account number |
| 2 | Set order number |
| 3 | Set validation flag |
| 4 | Set new limit |
| 5 | Process change order |
|
Warning
By default validation parameter equals WITHOUT_VALIDATION and accept quote request will directly routed to the market. If you want only check a validity of the request, then you need to set validation parameter to VALIDATE_ONLY. An order will validated by the backend system, but will not be routed to the market. It’s very useful for the test goals. |
Cancel order
To cancel order is necessary to have order number of existing order and an account with this order linked in. The order can be canceled if the status of the orders allowes that.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private void cancelOrder(Order order, TradingAccount account) {
if (order!=null) {
String orderNumber = order.getOrderNumber();
if (orderNumber!=null && !orderNumber.isEmpty()) {
CancelOrderRequest cancelOrderRequest = CancelOrderRequest.newBuilder()
.setAccessToken(accessToken)
.setAccountNumber(account.getAccountNumber()) (1)
.setOrderNumber(order.getOrderNumber()) (2)
.setValidation(Validation.VALIDATE_ONLY) (3)
.build();
OrderReply cancelOrderReply = (4)
orderServiceBlockingStub.cancelOrder(cancelOrderRequest);
System.out.println(cancelOrderReply);
}
}
}
| 1 | Set account number |
| 2 | Set order number |
| 3 | Set validation flag |
| 4 | Process change order |
|
Warning
By default validation parameter equals WITHOUT_VALIDATION and accept quote request will directly routed to the market. If you want only check a validity of the request, then you need to set validation parameter to VALIDATE_ONLY. An order will validated by the backend system, but will not be routed to the market. It’s very useful for the test goals. |
Activate order
Activate order function used to activate inactive order and route an order to the market. This function available only in pro version of the ActiveTrader.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private void activateOrder(Order order, TradingAccount account) {
if (order!=null) {
String orderNumber = order.getOrderNumber();
if (orderNumber!=null && !orderNumber.isEmpty()) {
ActivateOrderRequest activateOrderRequest = ActivateOrderRequest.newBuilder()
.setAccessToken(accessToken)
.setAccountNumber(account.getAccountNumber()) (1)
.setOrderNumber(order.getOrderNumber()) (2)
.setValidation(Validation.VALIDATE_ONLY) (3)
.build();
OrderReply changeOrderReply = (4)
orderServiceBlockingStub.activateOrder(activateOrderRequest);
System.out.println(changeOrderReply);
}
}
}
| 1 | Set account number |
| 2 | Set order number |
| 3 | Set validation flag |
| 4 | Process activate order |
Deactivate order
Deactivate order function used to deactivate active order and remove an order from the market. This function available only in pro version of the ActiveTrader.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private void deactivateOrder(Order order, TradingAccount account) {
if (order!=null) {
String orderNumber = order.getOrderNumber();
if (orderNumber!=null && !orderNumber.isEmpty()) {
DeactivateOrderRequest deactivateOrderRequest = DeactivateOrderRequest.newBuilder()
.setAccessToken(accessToken)
.setAccountNumber(account.getAccountNumber()) (1)
.setOrderNumber(order.getOrderNumber()) (2)
.setValidation(Validation.VALIDATE_ONLY) (3)
.build();
OrderReply changeOrderReply = (4)
orderServiceBlockingStub.deactivateOrder(deactivateOrderRequest);
System.out.println(changeOrderReply);
}
}
}
| 1 | Set account number |
| 2 | Set order number |
| 3 | Set validation flag |
| 4 | Process deactivate order |
Order costs
BaFin Rules
The law allowes to execute orders only after requesting of the order costs with a possibility to decline order in the case if order costs are not accepted. That follows to request order cost before order execution. The order execution without requesting of the order costs is not allowed.
Processing of the order costs
You can request an information about estimated order costs in AddOrderRequest and AcceptQuoteRequest.
|
Warning
OrderCost contains only estimated values. The real values are depended from real execution quotes, time of the execution and other parameters. |
To request cost information is need to execute orders requests with Validation values VALIDATE_WITH_TOTAL_COSTS, TOTAL_COST_ONLY or VALIDATE_WITH_DETAIL_COSTS. In first and second cases only total or aggregated costs are calculated. In second case detail information about costs is delivered. In all cases only validation of the request is happened, without real execution. To execute order you have to repeat same request with Validation WITHOUT_VALIDATION type.
|
Important
During prepartion phase TOTAL_COST_ONLY validation type can be replaced with VALIDATE_WITH_TOTAL_COSTS type. |
All order costs can be checked in the online archive.
Error handling
If no costs are avialable or costs information is outdated then by the order execution will be return ORD_COSTS_ABSENT_ERR error. In such cases is necessary to repeat order costs request and order execution request.
|
Useful
To speed up order execution and save time by the order placement it’s possible to prepare and validate order with VALIDATE_WITH_TOTAL_COSTS or TOTAL_COST_ONLY flags and some time later execute the same order with WITHOUT_VALIDATION flag. The host system will recognize parameters of the order and will forward order directly to the market. Otherwise to fullfil all BaFin requirements host system will request order costs before the order execution. In the each case the information about order costs will be placed into online archive before the order execution. |
|
Warning
This request doesn’t send order to the market, but validates only. As the result no real order is placed into the system. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private OrderReply getOrderCosts() {
SecurityCode securityCode = TestUtils.getSecurityCode("710000", SecurityCodeType.WKN); (1)
StockExchange stockExchange = TestUtils.getStockExchange("ETR", null); (2)
SecurityWithStockExchange securityWithStockExchange =
TestUtils.getSecurityWithStockExchange(securityCode, stockExchange); (3)
AddOrderRequest request = AddOrderRequest.newBuilder() (4)
.setAccessToken(accessToken)
.setAccountNumber("123456789") (5)
.setSecurityWithStockexchange(securityWithStockExchange)
.setValidation(Validation.VALIDATE_WITH_TOTAL_COSTS) (6)
// .setValidation(Validation.VALIDATE_WITH_DETAIL_COSTS) (7)
.setAmount(1)
.setOrderModel(OrderModel.LIMIT)
.setLimit(1)
.setOrderType(OrderType.BUY)
.setCashQuotation(CashQuotation.KASSA)
.setValidityDate(TestUtils.getDate(GregorianCalendar.getInstance()))
.build();
OrderReply addOrderReply = orderServiceBlockingStub.addOrder(request); (8)
OrderCosts orderCosts = addOrderReply.getOrderCosts(); (9)
double estimatedTotalCosts = orderCosts.getEstimatedTotalCosts();
for (CategoryCost categoryCost : orderCosts.getCategorieCostsList()) {
double totalSumAbsolute = categoryCost.getTotalSumAbsolute();
//
}
System.err.println(addOrderReply);
return addOrderReply;
}
| 1 | Prepare security code |
| 2 | Prepare stock exchange |
| 3 | Prepare security with stock exchange |
| 4 | Prepare request |
| 5 | Set order parameters |
| 6 | Set validation with total costs |
| 7 | Alternative: Set validation with detail costs |
| 8 | Process order add |
| 9 | Extract order costs |
Early request of the order costs
|
Useful
It’s possible to prepare an order for the execution and keep an infomation about order costs for the future execution without additional checks. This information will be cached in the application and reused by the real order execution. No additional steps will be performed. All data about order costs will be (additionally) avialible in the online archive. It’s important to understand that sometime costs information can be absolette. In this case an order execution will be failed with the error ORD_COSTS_NOT_REQUESTED. In such cases is need to repeat order costs request and order execution request. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private OrderReply addOrderWithCostsRequest() {
SecurityCode securityCode = TestUtils.getSecurityCode("710000", SecurityCodeType.WKN); (1)
StockExchange stockExchange = TestUtils.getStockExchange("ETR", null); (2)
SecurityWithStockExchange securityWithStockExchange =
TestUtils.getSecurityWithStockExchange(securityCode, stockExchange); (3)
Builder requestBuilder = AddOrderRequest.newBuilder() (4)
.setAccessToken(accessToken)
.setAccountNumber("123456789") (5)
.setSecurityWithStockexchange(securityWithStockExchange)
.setAmount(1)
.setOrderModel(OrderModel.LIMIT)
.setLimit(1)
.setOrderType(OrderType.BUY)
.setCashQuotation(CashQuotation.KASSA)
.setValidityDate(TestUtils.getDate(GregorianCalendar.getInstance()));
AddOrderRequest costsRequest = requestBuilder
.setValidation(Validation.TOTAL_COSTS_ONLY) (6)
.build();
OrderReply costsReply = orderServiceBlockingStub.addOrder(costsRequest); (7)
if (costsReply.getError()!=Error.getDefaultInstance()) {
System.err.print("Error: "+costsReply.getError());
return costsReply;
}
// Can be later
AddOrderRequest executionRequest = requestBuilder
.setValidation(Validation.WITHOUT_VALIDATION) (8)
.build();
OrderReply executionReply = orderServiceBlockingStub.addOrder(executionRequest); (9)
System.err.println(executionReply);
return executionReply;
}
| 1 | Prepare security code |
| 2 | Prepare stock exchange |
| 3 | Prepare security with stock exchange |
| 4 | Prepare request |
| 5 | Set order parameters |
| 6 | Set validation only with total costs |
| 7 | Process costs calulation request |
| 8 | Prepare real order add request (Warning real execution) |
| 9 | Process order execution |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private final OrderServiceGrpc.OrderServiceBlockingStub orderServiceBlockingStub;
private void acceptQuoteWithCostsRequest() {
SecurityCode securityCode = TestUtils.getSecurityCode("710000", SecurityCodeType.WKN);
StockExchange stockExchange = TestUtils.getStockExchange("OTC", null);
SecurityWithStockExchange securityWithStockExchange = TestUtils.getSecurityWithStockExchange(securityCode, stockExchange);
AcceptQuoteRequest costsRequest = AcceptQuoteRequest.newBuilder() (1)
.setAccessToken(accessToken)
.setOrderType(OrderType.BUY)
.setSecurityWithStockexchange(securityWithStockExchange)
.setAmount(10)
.setValidation(Validation.TOTAL_COSTS_ONLY) (2)
//.setLimit(10) (3)
//.setQuoteReference() (4)
.build();
OrderReply costsReply = orderServiceBlockingStub.acceptQuote(costsRequest); (5)
if (costsReply.getError()!=Error.getDefaultInstance()) {
System.err.print("Error: "+costsReply.getError());
return;
}
// Later
QuoteRequest quoteRequest = QuoteRequest.newBuilder() (6)
.setAccessToken(accessToken)
.setOrderType(OrderType.BUY)
.setSecurityCode(securityCode)
.setAmount(10)
.addStockExchanges(stockExchange)
.build();
PerformanceCounter pcGetQuote = new PerformanceCounter("GetQuote");
QuoteReply quoteReply = orderServiceBlockingStub.getQuote(quoteRequest); (7)
pcGetQuote.print();
if (quoteReply.getError()==Error.getDefaultInstance()) {
QuoteEntry quoteEntry = quoteReply.getPriceEntries(0); (8)
if (quoteEntry.getError()==Error.getDefaultInstance() &&
!quoteEntry.getQuoteReference().isEmpty()) { (9)
AcceptQuoteRequest acceptQuoteRequest = AcceptQuoteRequest.newBuilder() (10)
.setAccessToken(accessToken)
.setOrderType(OrderType.BUY)
.setSecurityWithStockexchange(securityWithStockExchange)
.setAmount(10)
.setValidation(Validation.WITHOUT_VALIDATION) (11)
.setLimit(quoteEntry.getBuyPrice())
.setQuoteReference(quoteEntry.getQuoteReference()) (12)
.build();
OrderReply acceptQuote = orderServiceBlockingStub.acceptQuote(acceptQuoteRequest); (13)
System.err.println(acceptQuote);
}
}
}
| 1 | Prepare costs request |
| 2 | Set validation only with total costs |
| 3 | Limit is optional |
| 4 | Quote reference can be empty |
| 5 | Process costs calulation request |
| 6 | Prepare quote request |
| 7 | Process quote request |
| 8 | Get entry for the quote |
| 9 | Check quote |
| 10 | Prepare accept quote request |
| 11 | Set validation (Warning real execution) |
| 12 | Set quote reference |
| 13 | Process order execution |
Errors
| Error code | Target | Description |
|---|---|---|
ACC_NOT_TRADING_ERR |
Ordering |
Process order with not trading account |
ACC_NOT_VALID_ERR |
Ordering |
Process order with invalid account |
ORD_ACTIVE_ERR |
Ordering |
Inactivate order in non pro version |
ORD_AMOUNT_ERR |
Ordering |
Orders amount is not changable for selected order |
ORD_DRIPPING_QUANTITY_ERR |
Ordering |
Dripping quantity error |
ORD_COSTS_ERR |
Ordering |
Order costs information unavialable |
ORD_COSTS_ABSENT_ERR |
Ordering |
Order costs information is not cached. |
ORD_LIMIT_ERR |
Ordering |
Limit field is invalid |
ORD_MODEL_ERR |
Ordering |
Order model is wrong |
ORD_NOT_CANCELABLE_ERR |
Ordering |
Order is not cancelable |
ORD_NOT_KNOWN_ERR |
Ordering |
Order is not known by the system |
ORD_STOP_ERR |
Ordering |
Order stop is not changable |
ORD_STOP_LIMIT_ERR |
Ordering |
Stop limit is not changable |
ORD_TRALING_DISTANCE_ERR |
Ordering |
Traling distance is not changable |
ORD_TRALING_LIMIT_TOLERANCE_ERR |
Ordering |
Traling limit tolerance is not changable |
ORD_VALIDITY_DATE_ERR |
Ordering |
Validity date is not changable |
ORD_WRONG_PRICE_TICKET_ERR |
Ordering |
Price ticket is not correct for this accept quote |
ORD_QUOTE_ERR |
Ordering |
Quote is not valid |
ORD_VALIDATION_ERR |
Ordering |
Selected validation can not be use for this request |
ORD_COSTS_NOT_REQUESTED |
Ordering |
Costs are not requested before order or costs information is old |
STK_NOT_FOUND_ERR |
Stocks |
Stock exchange is unknown |
INTERNAL_ERR |
System |
Internal engine error |
SYSTEM_ERR |
System |
GRPC error |
UNSUPPORTED_OPERATION_ERR |
System |
Operation is not supported |
Objects and types description
AcceptQuoteRequest
Accept quote request represents information about one order that should be placed on the short term market
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
account_number |
string |
Trading account number |
security_with_stockexchange |
Security code with stock exchange |
|
order_type |
Order type. It should be relevant to the requested GetQuoteRequest |
|
amount |
double |
Amount, It should be relevant to the requested GetQuoteRequest |
limit |
double |
Limit |
quote_reference |
string |
Quote reference from GetQuoteRequest |
validation |
Validation flag.
If value is WITHOUT_VALIDATION then backend system sends order actions directly to the market. |
|
risk_class_override |
bool |
Risk class override flag. If true then allowes override user risk class |
target_market_override |
bool |
Target market override flag. If true then allowes override target market |
tax_nontransparent_override |
bool |
Tax non trasparent override flag. If true then allowes override tax intransparesity |
accept_additional_fees |
bool |
Accept additinal fees flag. If true then allowes accept non transparent fees |
AccessTokenRequest
Access token request contains an access token data
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
ActivateOrderRequest
Activate order request represents information for activation of one inactive order pro only
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
account_number |
string |
Trading account number |
order_number |
string |
Order number for that this changes should be accepted |
validation |
Validation flag. This request allowes only WITHOUT_VALIDATION
and VALIDATE_ONLY values. |
AggregatedCosts
Aggregated costs contain an information about estimated costs for the selected order
| Field | Type | Description |
|---|---|---|
in_costs_absolute |
double |
In costs for the order |
in_costs_relative |
double |
Percentage part of the in costs |
in_costs_currency |
string |
Currency for the in costs |
out_costs_absolute |
double |
Out costs for the order |
out_costs_relative |
double |
Percentage part of the out costs |
out_costs_currency |
string |
Currency for the out costs |
instrument_costs_absolute |
double |
Instrument costs for the order |
instrument_costs_relative |
double |
Percentage part of the instrument costs |
instrument_costs_currency |
string |
Currency for the instrument costs |
service_costs_absolute |
double |
Service costs for the order |
service_costs_relative |
double |
Percentage part of the service costs |
service_costs_currency |
string |
Currency for the servcie costs |
subsidy_costs_absolute |
double |
Subsidy costs for the order |
subsidy_costs_relative |
double |
Percentage part of the subsidy costs |
subsidy_costs_currency |
string |
Currency for the subsidy costs |
foreign_currency_costs_absolute |
double |
Foreign currency costs for the order |
foreign_currency_costs_relative |
double |
Percentage part of the foreign currency costs |
foreign_currency_costs_currency |
string |
Currency for the foreign currency costs |
performance_impact_absolute |
double |
Performance impact for the order |
performance_impact_relative |
double |
Percentage part of the performance impact |
performance_impact_currency |
string |
Currency for the performance impact |
expected_amount |
double |
Expected amount estimated for the order |
expected_amount_currency |
string |
Currency for the expected amount |
AddOrderRequest
Add order request represents order data for the long term markets
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
account_number |
string |
Trading account number which used for the execution |
security_with_stockexchange |
Security code with stock exchange |
|
order_type |
Order type |
|
amount |
double |
Amount of the securities |
order_model |
Order model |
|
order_supplement |
Order supplement |
|
cash_quotation |
Cach quotation |
|
validity_date |
Order validity date |
|
limit |
double |
Limit value |
stop |
double |
Stop value. This value can be used only together with StopMarket, StopLimit and OneCancelOter order models. |
stop_limit |
double |
Stop limit used in the StopLimit and OneCancelOther order models |
trailing_distance |
double |
Traling distance in traling notation units or empty value |
trailing_notation |
Trailing notation for the trailing orders |
|
trailing_limit_tolerance |
double |
Trailing limit tolerance for the trailing orders |
dripping_quantity |
double |
Dripping quantity pro only |
position_id |
string |
Position id of the depot position. It used only for sale certainly securities from depot |
validation |
Validation flag.
If value is WITHOUT_VALIDATION then backend system sends order actions directly to the market. |
|
risk_class_override |
bool |
Risk class override flag. If true then allowes override user risk class |
target_market_override |
bool |
Target market override flag. If true then allowes override target market |
tax_nontransparent_override |
bool |
Tax non trasparent override flag. If true then allowes override tax intransparesity |
accept_additional_fees |
bool |
Accept additinal fees flag. If true then allowes accept non transparent fees |
closed_realestate_fond_override |
bool |
Closed realestate fond override. If true then allowes sell fonds over fds |
inactive |
bool |
Inactive order flag, pro only. If true then order market as inactive and don’t routed to the marker. To activate order please use ActivateOrder function |
CancelOrderRequest
Cancel order request represents canceling information for one order on the market or one inactive order
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
account_number |
string |
Trading account number |
order_number |
string |
Order number for that this changes should be accepted |
validation |
Validation flag. This request allowes only WITHOUT_VALIDATION value. |
CashQuotation
Cash quotation is additional parameter of the order
| Field | Description |
|---|---|
NOTHING |
Quotation is not defined |
KASSA |
Kassa quotation |
AUCTION |
Auction quotation |
OPENING |
Opening quotation |
INTRADAY |
Intraday quotation |
CLOSING |
Close quotation |
CategoryCost
Represents one category cost.
| Field | Type | Description |
|---|---|---|
category_id |
string |
Category id |
category_label |
string |
Human redable category label |
total_sum_absolute |
double |
Total absolute sum of the children values |
total_sum_relative |
double |
Total relative sum of the children values |
currency |
string |
Currency for absolute sum |
detail_costs |
List of DetailCost |
List of child values or detailed information. |
ChangeOrderRequest
Change order request contains parameters for the order change. Be careful: not all combinations are possible.
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
account_number |
string |
Trading account number |
order_number |
string |
Order number for that this changes should be accepted |
limit |
double |
New limit, shouldn’t filled for market order |
stop |
double |
New stop value |
stop_limit |
double |
New stop limit value |
amount |
double |
New amount |
validity_date |
New validity date |
|
order_model |
New order model |
|
order_supplement |
New order supplement |
|
dripping_quantity |
double |
Dripping quantity pro only |
validation |
Validation flag. This request allowes only WITHOUT_VALIDATION
and VALIDATE_ONLY values. |
|
trailing_distance |
double |
New trailing distance |
trailing_limit_tolerance |
double |
New traling limit tolerance |
CurrencyRateReply
Returns currency rate
| Field | Type | Description |
|---|---|---|
currency_from |
string |
Source currency |
currency_to |
string |
Target currency |
currency_rate |
double |
Currency rate |
error |
Error information if occuirs |
CurrencyRateRequest
CurrencyRateRequest used for the determination of the currency rate from one currency rate to second currency. Results depends from user market data aboniment and can be realtime or delayed.
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
currency_from |
string |
Source currency |
currency_to |
string |
Target currency |
Date
Represents a whole calendar date, e.g. date of birth. The time of day and
time zone are either specified elsewhere or are not significant. The date
is relative to the Proleptic Gregorian Calendar. The day may be 0 to
represent a year and month where the day is not significant, e.g. credit card
expiration date. The year may be 0 to represent a month and day independent
of year, e.g. anniversary date. Related types are [google.type.TimeOfDay][google.type.TimeOfDay]
and google.protobuf.Timestamp
.
| Field | Type | Description |
|---|---|---|
year |
int32 |
Year of date. Must be from 1 to 9999, or 0 if specifying a date without a year. |
month |
int32 |
Month of year. Must be from 1 to 12. |
day |
int32 |
Day of month. Must be from 1 to 31 and valid for the year and month, or 0 if specifying a year/month where the day is not significant. |
DeactivateOrderRequest
Deactivate order request represents information for deactivation of one active order pro only
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
account_number |
string |
Trading account number |
order_number |
string |
Order number for that this changes should be accepted |
validation |
Validation flag. This request allowes only WITHOUT_VALIDATION and VALIDATE_ONLY values. If value is WITHOUT_VALIDATION then backend system sends order actions directly to the market. If value is VALIDATE_ONLY then backend system doesn’t send order actions to the market, but validate order parameters |
DepotEntries
| Field | Type | Description |
|---|---|---|
account |
Trading account |
|
entries |
List of DepotEntry |
Depot entries list |
error |
Error information if occuirs |
DepotEntry
Depot entry contains information about one security in the depot. This entry combines data from one or more depot positions
| Field | Type | Description |
|---|---|---|
security_code |
Security code |
|
positions |
List of DepotPosition |
List of linked depot positions. This list contains at least one element |
effective_amount |
double |
Effective amount |
scheduled_amount |
double |
Scheduled amount |
total_amount |
double |
Total amount of the securities |
sell_possible |
bool |
True if sell possible for this entry or false otherwise. This value can be true only if all child positions have sell_possible = true |
unit_note |
Unit note |
|
blocked |
bool |
True if entry is blocked or false otherwise |
purchase_quotation |
double |
Purchase quotation or NaN if not defined |
purchase_currency |
string |
Purchase currency or empty value if not defined |
purchase_currency_rate |
double |
Purchase currency rate or NaN if not defined |
open_sales |
double |
Open sales |
DepotPosition
Depot posiotion contains information about one position in the depot
| Field | Type | Description |
|---|---|---|
amount |
double |
Ammount of the securities |
position_id |
string |
Position identification |
sell_possible |
bool |
True if sell of the position is possible or false otherwise |
unit_note |
Unit note |
|
blocked |
bool |
True if entry is blocked or false otherwise |
purchase_quotation |
double |
Purchase quotation or NaN if not defined. Currently this field ALWAYS undefined, reserved for future use |
purchase_currency |
string |
Purchase currency or empty value if not defined |
purchase_currency_rate |
double |
Purchase currency rate or NaN if not defined |
DetailCost
Detail cost contains one entry for the selected category
| Field | Type | Description |
|---|---|---|
detail_id |
string |
Detail id |
detail_label |
string |
Human redable detail label |
value_absolute |
double |
Absolute value for this entry |
value_relative |
double |
Relative value for this entry |
currency |
string |
Currency for this entry |
detail_type |
string |
Specific entry type |
LimitToken
Limit token represents a possibility to trade on the short term markets (AcceptQuote) and long term markets (AddOrder)
| Field | Description |
|---|---|
LIMIT_AND_QUOTE |
AcceptQuote and AddOrder possible |
QUOTE_ONLY |
AcceptQuote only possible |
LIMIT_ONLY |
AddOrder only possible |
LoginReply
Login reply provides information that need for the access to the TAPI
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token is used in each request by the access to the TAPI. |
error |
Error information if occuirs |
LoginRequest
Login request provides data for initial access to the TAPI
| Field | Type | Description |
|---|---|---|
secret |
string |
Secret is user defined access string. It’s not possible to restore this secret directly. See double MD5 hash logic + salt |
Order
Order represent one order object
| Field | Type | Description |
|---|---|---|
security_with_stockexchange |
Security with stock echange |
|
order_type |
Order type |
|
order_number |
string |
Order number |
amount |
double |
Amount of the securities |
order_model |
Order model |
|
order_supplement |
Order supplement |
|
cash_quotation |
Cache quotation |
|
executed_amount |
double |
Executed amount |
order_status |
Order status |
|
status_timestamp |
Date and time of the order status |
|
validity_date |
Validity date of the order |
|
limit |
double |
Limit value. Used as the order limit for all Limit order model with exception of the StopLimit order model. For this order model please use stop limit field. |
stop |
double |
Stop value. This value can be used only together with StopMarket, StopLimit and OneCancelOter order models. |
stop_limit |
double |
Stop limit value Can be used only tigether with the StopLimit order model. The meaning of the value is limit of the order after stop. |
trailing_distance |
double |
Traling distance in traling notation units or empty value |
trailing_notation |
Trailing notation for the trailing orders |
|
trailing_limit_tolerance |
double |
Trailing limit tolerance for the trailing orders |
dripping_quantity |
double |
Dripping quantity pro only |
trading_partner_name |
string |
Trading partner name |
execution_quote |
double |
Execution quote for the executed amount |
unique_id |
string |
Unique id of the order. Used for the order matching. In the pro version of the ActiveTrader order_number can be changed after activation / deactivation. All order activities need actual or delivered form the system order_number. Typical scenario is to map and update unique id to the order number delivered from the API. |
OrderBookEntry
Orderbook entry contains data about one level of the order book. This is bid price, ask price, bid volume, ask volume. Entries with lower index have lower ask and higer bid prices.
| Field | Type | Description |
|---|---|---|
bid_price |
double |
Bid price |
ask_price |
double |
Ask price |
bid_volume |
double |
Bid volume |
ask_volume |
double |
Ask volume |
OrderCosts
Order costs represents information about order action estimated costs. This information is only estimated values and is depended from real execution quotes, time, etc.
| Field | Type | Description |
|---|---|---|
estimated_total_costs |
double |
Estimated total cost for order action |
cost_id |
string |
Reference backend cost id |
categorie_costs |
List of CategoryCost |
List of the cost categories. Filled only by validation request with detailed information. |
aggregated_costs |
Aggregated costs for the order. Filled only by validation request with validation information. |
OrderModel
Order model represents possible orders
| Field | Description |
|---|---|
NO_ORDER_MODEL |
Order model absent |
MARKET |
Market order |
LIMIT |
Limit order |
STOP_MARKET |
Stop market order. |
STOP_LIMIT |
Stop limit order |
ONE_CANCELS_OTHER_MARKET |
One cancels other market order |
ONE_CANCELS_OTHER_LIMIT |
One cancels other limit order |
TRAILING_STOP_MARKET |
Trailing stop market order |
TRAILING_STOP_LIMIT |
Trailing stop limit order |
OrderReply
Order reply represents result of the add order or accept quote requests
| Field | Type | Description |
|---|---|---|
account |
Trading account |
|
order |
Result order |
|
order_costs |
Order costs. This field contains data if order costs are requested |
|
error |
Error information if occuirs |
Orders
Orders represent pushed information about orders from one trading accounts
| Field | Type | Description |
|---|---|---|
account |
Trading account |
|
orders |
List of Order |
List of the orders |
error |
Error information if occuirs |
OrderStatus
Order status represents status of the order
| Field | Description |
|---|---|
NO_ORDER_STATUS |
Status is not defined |
NEW |
New order |
OPEN |
Open order |
EXECUTED |
Fully executed order |
PARTIALLY_EXECUTED |
Partially executed order |
CANCELED |
Canceled order |
CANCELED_FORCED |
Canceled forced order |
CANCELED_NOTED |
Canceling noted order |
CANCELED_TIMEOUT |
Canceling timeout order |
CHANGED |
Changed order |
CHANGED_NOTED |
Changing noted order |
INACTIVE |
Inactive order pro only |
INACTIVE_NOTED |
Inactivation noted order pro only |
STORNO |
Storno order |
OrderSupplement
Order supplement is additional parameter by order definition
| Field | Description |
|---|---|
NORMAL |
Normal order supplement |
IMMIDIATE_OR_CANCEL |
Immidiate or cancel order supplement |
FILL_OR_KILL |
Fill or kill order supplement |
ICEBERG |
Icesberg order supplement. Allowes to delivery amount in portions. pro only |
MARKET_PRICE |
Market place order supplement |
OrderType
Order type represents different buy / sell order possibilities
| Field | Description |
|---|---|
NO_ORDER_TYPE |
Order type is not defined |
BUY |
Buy order type |
SELL |
Sell order type |
SHORT_SELL |
Short sell order type |
SHORT_COVER |
Short cover order type. This type is not allowed as input parameter |
FORCED_COVER |
Rorced cover order type. This type is not allowed as input parameter |
PriceEntry
| Field | Type | Description |
|---|---|---|
open_price |
double |
Open price |
close_price |
double |
Close price |
high_price |
double |
High price |
low_price |
double |
Low price |
volume |
double |
Volume, can not be filled |
open_time |
Open time |
|
close_time |
Close time |
QuoteEntry
Quote entry represents one answer with quote information from one stock exchange This reply contains both buy and sell price. The quote reference can be used only with requested order type. Second value is present only for information goals.
order type: BUY -> quote reference for buy price and reference, sell price and reference are informative only order type: SELL -> quote reference for sell price and reference, buy price and reference are informative only
| Field | Type | Description |
|---|---|---|
stock_exchange |
Stock exchange where infomation was requested |
|
buy_price |
double |
Buy price |
buy_volume |
double |
Buy volume |
sell_price |
double |
Sell price |
sell_volume |
double |
Sell volume |
last_price |
double |
Last price |
last_volume |
double |
Last volume |
last_time |
Date and time of the last price |
|
currency |
string |
Currency |
quote_reference |
string |
Quote reference. Used for the accept quite request. Can be empty if accept quote is not possible. |
order_type |
Used by call order type |
|
error |
Error information if occuirs |
QuoteReply
Quote reply represents data with quote answers from requested markets
| Field | Type | Description |
|---|---|---|
security_code |
Security code |
|
order_type |
Order type |
|
price_entries |
List of QuoteEntry |
List of the quites |
error |
Error information if occuirs |
QuoteRequest
Quote request represents data to get information about actual quotes on the selected makets
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
security_code |
Security code |
|
order_type |
Order type. Only BUY or SELL are allowed |
|
amount |
double |
Amount of securities. Relevant to the short term markets |
stock_exchanges |
List of StockExchange |
List of stock exchanges |
SecurityChangedField
SecurityChangedField represents information about changed fields during marked data event. Not all field can be initialized. There are only changed fields. Some fields can be changed, but have undefined state for example NaN.
| Field | Description |
|---|---|
NONE |
No data |
LAST_PRICE |
Price of the last trade |
LAST_VOLUME |
Volume last trade |
LAST_DATE_TIME |
Last quote date and time |
TODAY_NUM_TRADES |
Today number of tradings |
TODAY_VOLUME |
Today volume |
ASK_PRICE |
Last ask price |
ASK_VOLUME |
Volume last ask |
ASK_TIME |
Time of the last ask |
BID_PRICE |
Last bid price |
BID_VOLUME |
Volume last bid |
BID_TIME |
Time of the last bid |
PREVIOUS_PRICE |
Quote of the previous trading day |
PREVIOUS_DATE |
Date of the previous trading day |
RELATIVE_DIFF |
Relative difference to the previous day |
ABS_DIFF |
Absolute difference to the previous day |
HIGH_PRICE |
Highest price |
LOW_PRICE |
Lowest price |
OPEN_PRICE |
Price at opening |
WEEK_HIGH_PRICE |
Highest price of the previous week |
DATE_WEEK_HIGH |
Date of highest price of the previous week |
WEEK_LOW_PRICE |
Lowest price of the previous week |
DATE_WEEK_LOW |
Date of lowest price of the previous week |
MONTH_HIGH_PRICE |
Highest price of the previous month |
DATE_MONTH_HIGH |
Date of highest price of the previous month |
MONTH_LOW_PRICE |
Lowest price of the previous month |
DATE_MONTH_LOW |
Date of lowest price of the previous month |
YEAR_HIGH_PRICE |
Highest price of the current year |
DATE_YEAR_HIGH |
Date of the highest price of the current year |
YEAR_LOW_PRICE |
Lowest price of the current year |
DATE_YEAR_LOW |
Date of the lowest price of the current year |
LAST_ADDENDUM |
Addendum of the last price. |
TRADING_PHASE |
Trading phase |
INDICATIVE_PRICE |
Indicative price |
PREVALENCE_VOLUME |
Trading volume corresponding to the last price |
SecurityClass
Represents information about security class
| Field | Description |
|---|---|
NO_SECURITY_CLASS |
Security class is undefined on unknown |
STOCK |
Stock security class |
BOND |
Bond security class |
CERTIFICATE |
Certificate security class |
PRECIOUS_METAL |
Precious metal security class |
PARTICIPATION_CERTIFICATE |
Participation certificate security class |
FUNDS |
Funds security class |
MUTUAL_FUNDS |
Mutual funds security class |
WARRANT |
Warrants security class |
FUTURE |
Futures security class |
INDEX |
Indexies security class |
OTHERS |
Other securities security class |
FUTURE_C1 |
Future c1 security class |
FUTURE_C2 |
Future c2 security class |
FUTURE_C3 |
Future c3 security class |
TRACKERS |
Trackers security class |
CURRENCY |
Currency security class |
COMMODITY |
Commodity security class |
SecurityCode
| Field | Type | Description |
|---|---|---|
code |
string |
Security code |
code_type |
Security code type (WKN, ISIN, etc) |
SecurityCodeType
Represents information about security code type Some of the types are refer to the market data provider (FactSet)
| Field | Description |
|---|---|
NO_CODE_TYPE |
Unknown code type |
WKN |
WKN code type |
ISIN |
ISIN code type |
ID_NOTATION |
Factset id notation |
ID_OSI |
Factset id osi |
ID_INSTRUMENT |
Factset id instrument |
MNEMONIC |
Mnemonic or symbol |
MNEMONIC_US |
US Mnemonic or symbol |
SecurityInfoReply
Returns security information
| Field | Type | Description |
|---|---|---|
name |
string |
Security name |
security_class |
Security class |
|
security_codes |
List of SecurityCode |
Security codes with security type (WKN, ISIN, etc) |
stock_exchange_infos |
List of SecurityStockExchangeInfo |
Stockexchange info (stock exchange, name) |
unit_note |
Unit note |
|
error |
Error information if occuirs |
SecurityInfoRequest
Requests security information for security code
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
security_code |
Security code with security type (WKN, ISIN) |
SecurityMarketDataReply
Returns market data information
| Field | Type | Description |
|---|---|---|
security_with_stockexchange |
Security with stockExchange object (security code, stock exchange) |
|
changed_fields |
List of SecurityChangedField |
Security fields, which were changed |
currency |
string |
Currency |
last_price |
double |
Fields Price of the last trade |
last_volume |
double |
Volume last trade |
last_date_time |
Last quote date and time |
|
today_num_trades |
int32 |
Today number of tradings |
today_volume |
double |
Today volume |
ask_price |
double |
Last ask price |
ask_volume |
double |
Volume last ask |
ask_time |
Time of the last ask |
|
bid_price |
double |
Last bid price |
bid_volume |
double |
Volume last bid |
bid_time |
Time of the last bid |
|
previous_price |
double |
Quote of the previous trading day |
previous_date |
Date of the previous trading day |
|
relative_diff |
double |
Relative difference to the previous day |
abs_diff |
double |
Absolute difference to the previous day |
high_price |
double |
Highest price |
low_price |
double |
Lowest price |
open_price |
double |
Price at opening |
week_high_price |
double |
Highest price of the previous week |
date_week_high |
Date of highest price of the previous week |
|
week_low_price |
double |
Lowest price of the previous week |
date_week_low |
Date of lowest price of the previous week |
|
month_high_price |
double |
Highest price of the previous month |
date_month_high |
Date of highest price of the previous month |
|
month_low_price |
double |
Lowest price of the previous month |
date_month_low |
Date of lowest price of the previous month |
|
year_high_price |
double |
Highest price of the current year |
date_year_high |
Date of the highest price of the current year |
|
year_low_price |
double |
Lowest price of the current year |
date_year_low |
Date of the lowest price of the current year |
|
last_addendum |
string |
Addendum of the last price. |
trading_phase |
Trading phase |
|
indicative_price |
double |
Indicative price |
prevalence_volume |
double |
Trading volume corresponding to the last price |
error |
Error information if occuirs |
SecurityMarketDataRequest
Requests market data values for defined security with stockexchange
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
security_with_stockexchange |
Security with stockExchange object (security code, stock exchange) |
|
currency |
string |
Currency |
SecurityOrderBookReply
SecurityOrderBookReply represents information with orderbook market data. Currently this information is avialable for the Xetra stock exchange for the accepted for the second level market data instruments
| Field | Type | Description |
|---|---|---|
security_with_stockexchange |
Security with stock exchange object (security code, stock exchange) |
|
currency |
string |
Currency of the order book entries |
order_book_entries |
List of OrderBookEntry |
List of the order book entries |
error |
Error information if occuirs |
SecurityOrderBookRequest
Requests orderbook data for security with stockexchange
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
security_with_stockexchange |
Security with stockExchange object (security code, stock exchange) |
|
currency |
string |
Requested currency. If not filled used default currency. Otherwise values will be converted to requested currency. |
SecurityPriceHistoryReply
Returns history data for defined security
| Field | Type | Description |
|---|---|---|
security_with_stockexchange |
Security with stockExchange object (security code, stock exchange) |
|
currency |
string |
Currency |
price_entries |
List of PriceEntry |
List of the price entries |
error |
Error information if occuirs |
SecurityPriceHistoryRequest
Requests history data for one security on one stockexchange in intraday or historical format
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
security_with_stockexchange |
Security with stockExchange object (security code, stock exchange) |
|
days |
int32 |
Amount of the day in the past. This value should be positive. Maximal value for the intraday resolution is 15. |
time_resolution |
Time resolution for the data |
SecurityStockExchangeInfo
Security stock exchange info represents trading information about one security on the one market
| Field | Type | Description |
|---|---|---|
stock_exchange |
Stockexchange (id und issuer) |
|
buy_limit_token |
Possible limit token for buy orders |
|
sell_limit_token |
Possible limit token for sell orders |
|
buy_trading_types |
List of TradingPossibility |
Buy trading data (order models, order supplements, trailing notations) |
sell_trading_types |
List of TradingPossibility |
Sell trading data (order models, order supplements, trailing notations) |
maximal_order_date |
Maximal order validity date |
|
short_mode |
Short selling mode |
SecurityWithStockExchange
| Field | Type | Description |
|---|---|---|
security_code |
Security code object |
|
stock_exchange |
Stock exchange object |
| Function | Description |
|---|---|
LoginReply = Login(LoginRequest) |
Validates client by the TAPI and gets access data |
LogoutReply = Logout(LogoutRequest) |
Invalidates client by the TAPI and gets logout result |
| Function | Description |
|---|---|
TradingAccounts = GetTradingAccounts(AccessTokenRequest) |
Gets trading accounts @return TradingAccounts List of trading accounts |
TradingAccountInformation ⇐ StreamTradingAccount(TradingAccountRequest) |
Subscribes one trading account for updates @param TradingAccount Trading account for push @stream TradingAccountInformation Specific information for subscribed account (balance, kredit line, etc.) |
TradingAccountTransactions ⇐ StreamTradingAccountTransactions(TradingAccountRequest) |
Subscribes one trading account for the transactions updates @param TradingAccount Trading account for push @stream TradingAccountInformation Transactions list for subscribed account |
| Function | Description |
|---|---|
DepotEntries ⇐ StreamDepot(TradingAccountRequest) |
Subscribes one trading account for the depot data updates @param TradingAccount Trading account for push @stream DepotEntries depot entries linked to the account |
Empty = UpdateDepot(TradingAccountRequest) |
Initiates depot update action. All changes come by the StreamDepot subscription. This function doesn’t wait for the action result. @param TradingAccount Trading account for update |
| Function | Description |
|---|---|
Orders ⇐ StreamOrders(TradingAccountRequest) |
Subscribes one trading account for orders updates @param TradingAccount Trading account for push @stream Orders Orders list for seleted account |
Empty = UpdateOrders(TradingAccountRequest) |
Initiates orders update action. All changes come by the StreamOrders subscription. This function doesn’t wait for the action result. @param TradingAccount Trading account for update |
QuoteReply = GetQuote(QuoteRequest) |
Request market quote for the selected security on the selected stock exchanges. @param QuoteRequest quote request with interested security and stock exchanges @return QuoteReply quote reply with quotes |
OrderReply = AcceptQuote(AcceptQuoteRequest) |
Sends accept quote order request to the short term market @param AcceptQuoteRequest accept quote request with order parameters @return OrderReply result order or error |
OrderReply = AddOrder(AddOrderRequest) |
Sends long term order to the market @param AddOrderRequest order request with order parameters @return OrderReply result order or error |
OrderReply = ChangeOrder(ChangeOrderRequest) |
Sends order change request to the market @param ChangeOrderRequest changed order request with order parameters @return OrderReply result order or error |
OrderReply = CancelOrder(CancelOrderRequest) |
Sends order cancel request to the market @param CancelOrderRequest cancel order request with order reference @return OrderReply result order or error |
OrderReply = ActivateOrder(ActivateOrderRequest) |
Sends order activate request to the market. pro only @param ActivateOrderRequest activate order request with order parameters @return OrderReply result order or error |
OrderReply = DeactivateOrder(DeactivateOrderRequest) |
Sends order deactivate request to the market. pro only @param DeactivateOrderRequest deactivate order request with order parameters @return OrderReply result order or error |
| Function | Description |
|---|---|
SecurityInfoReply = GetSecurityInfo(SecurityInfoRequest) |
Gets security information about security @param SecurityInfoRequest Request object with interested security @return SecurityInfoReply Complete information about security |
SecurityMarketDataReply ⇐ StreamMarketData(SecurityMarketDataRequest) |
Subscribes security with stock exchange for market data updates @param SecurityMarketDataRequest Market data request with interested security and stock exchange @stream SecurityMarketDataReply Reply with all market data values |
SecurityOrderBookReply ⇐ StreamOrderBook(SecurityOrderBookRequest) |
Subscribes security with stock exchange for orderbook updates @param SecurityOrderBookRequest Orderbook data request with interested security and stock exchange @stream SecurityOrderBookReply Reply with all orderbook values |
CurrencyRateReply ⇐ StreamCurrencyRate(CurrencyRateRequest) |
Subscribes for currency rate from one currency to another currency. @param SecurityOrderBookRequest currency rate request with interested currencies from/to @stream CurrencyRateReply reply with currency rate |
SecurityPriceHistoryReply = GetSecurityPriceHistory(SecurityPriceHistoryRequest) |
Requests history data for one security on one stockexchange in intraday or historical format @param SecurityPriceHistoryRequest Data with security, stockexchange, how many days and resolution @return SecurityPriceHistoryReply List of the historical quotes or an error |
| Function | Description |
|---|---|
StockExchangeDescriptions = GetStockExchanges(AccessTokenRequest) |
Gets predefined stockexchages @return StockExchangeDescriptions list of stock exchange informations |
StockExchangeDescription = GetStockExchange(StockExchangeRequest) |
Gets specific stock exchange @param StockExchange Requested stock exchange @return StockExchangeDescription Stock exchange information |
ShortMode
Short mode gives information amout security shortability on the selected market.
| Field | Description |
|---|---|
NO_SHORT_MODE |
Undefined short selling |
YES |
Short selling is possible |
NO |
No short selling |
TEMPORARY_NO |
Temporary no short selling |
INTRADAY |
Intraday short selling |
OVERNIGHT |
Overnight short selling |
INTRADAY_AND_OVERNIGHT |
Intraday and Overnight short selling |
StockExchange
Stock exchange data
| Field | Type | Description |
|---|---|---|
id |
string |
Stock exchange id |
issuer |
string |
Stock exchange issuer. Can be null |
StockExchangeDescription
| Field | Type | Description |
|---|---|---|
stock_exchange_info |
Stock exchange information |
|
error |
Error information if occuirs |
StockExchangeDescriptions
| Field | Type | Description |
|---|---|---|
stock_exchange_infos |
List of StockExchangeInfo |
List with stock exchange information |
error |
Error |
StockExchangeInfo
| Field | Type | Description |
|---|---|---|
stockExchange |
Stock exchange object |
|
name |
string |
Stock exchange name |
StockExchangeRequest
Stock exchange request contains data that need to request stock exchange related data
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
stock_exchange |
Stock exchange |
TimeResolution
Time resolution represents information about price aggregation
| Field | Description |
|---|---|
NO_RESOLUTION |
Undefined resolution |
TICK |
Tick resolution. intraday. Be careful, in same cases there is a lot of data. |
SECOND |
Second resolution intraday |
MINUTE |
Minute resolution intraday |
HOUR |
Hour resolution intraday |
DAY |
Day resolution historic |
Timestamp
A Timestamp represents a point in time independent of any time zone or calendar, represented as seconds and fractions of seconds at nanosecond resolution in UTC Epoch time. It is encoded using the Proleptic Gregorian Calendar which extends the Gregorian calendar backwards to year one. It is encoded assuming all minutes are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By restricting to that range, we ensure that we can convert to and from RFC 3339 date strings. See https://www.ietf.org/rfc/rfc3339.txt.
Examples
Example 1: Compute Timestamp from POSIX time()
.
Timestamp timestamp; timestamp.set_seconds(time(NULL)); timestamp.set_nanos(0);
Example 2: Compute Timestamp from POSIX gettimeofday()
.
struct timeval tv; gettimeofday(&tv, NULL);
Timestamp timestamp; timestamp.set_seconds(tv.tv_sec); timestamp.set_nanos(tv.tv_usec * 1000);
Example 3: Compute Timestamp from Win32 GetSystemTimeAsFileTime()
.
FILETIME ft; GetSystemTimeAsFileTime(&ft); UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
// A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z // is<PHONE_NUMBER>0 seconds before Unix epoch 1970-01-01T00:00:00Z. Timestamp timestamp; timestamp.set_seconds((INT64) ((ticks / 10000000) -<PHONE_NUMBER>0LL)); timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
Example 4: Compute Timestamp from Java System.currentTimeMillis()
.
long millis = System.currentTimeMillis();
Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) .setNanos((int) ((millis % 1000) * 1000000)).build();
Example 5: Compute Timestamp from current time in Python.
timestamp = Timestamp() timestamp.GetCurrentTime()
JSON Mapping
In JSON format, the Timestamp type is encoded as a string in the RFC 3339 format. That is, the format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" where {year} is always expressed using four digits while {month}, {day}, {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone is required. A proto3 JSON serializer should always use UTC (as indicated by "Z") when printing the Timestamp type and a proto3 JSON parser should be able to accept both UTC and other timezones (as indicated by an offset).
For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 01:30 UTC on January 15, 2017.
In JavaScript, one can convert a Date object to this format using the
standard toISOString()
method. In Python, a standard datetime.datetime
object can be converted
to this format using strftime
with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
can use the Joda Time’s ISODateTimeFormat.dateTime()
to obtain a formatter capable of generating timestamps in this format.
Timestamp represents date + time format
| Field | Type | Description |
|---|---|---|
seconds |
int64 |
Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive. |
nanos |
int32 |
Non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanos values that count forward in time. Must be from 0 to 999,999,999 inclusive. |
TradingAccount
TradingAccount is trading account connected to the depot
| Field | Type | Description |
|---|---|---|
account_number |
string |
Account number |
depot_number |
string |
Depot number |
name |
string |
Name of the account owners |
tradable |
bool |
If account is tradable then true or false otherwise |
TradingAccountInformation
TradingAccountInformation contains specific for this account information
| Field | Type | Description |
|---|---|---|
account |
Trading account |
|
balance |
double |
Account balance |
credit_limit |
double |
Credit limit information |
buying_power |
double |
Buying power |
credit_limit_intraday |
double |
Credit limit intraday information, pro only |
buying_power_intraday |
double |
Buyng power intraday, pro only |
error |
Error information if occuirs |
TradingAccountRequest
Trading account request contains trading account related data
| Field | Type | Description |
|---|---|---|
access_token |
string |
Access token |
trading_account |
Trading account |
TradingAccounts
TradingAccounts contains account information from current session
| Field | Type | Description |
|---|---|---|
accounts |
List of TradingAccount |
List of trading accounts |
error |
Error information if occuirs |
TradingAccountTransactions
TradingAccountTransactions contains account transactions
| Field | Type | Description |
|---|---|---|
account |
Trading account |
|
transactions |
List of Transaction |
List of transactions |
error |
Error information if happened |
TradingPhase
Represents stock exchange trading phase. Some values are refer to the Xetra stock exchange
| Field | Description |
|---|---|
NONE |
Unknown trading phase |
PRETRADE |
Pretrade trading phase |
POSTTRADE |
Posttrade trading phase |
START |
Start trading phase |
END |
End trading phase |
VOLA |
Vola trading phase |
OCALL |
OCall trading phase |
ICALL |
ICall trading phase |
CCALL |
CCall trading phase |
TRADE |
Trade trading phase |
TRADE_INDICATIVE |
Trade indicative trading phase |
TRADE_BEST_BID_ASK |
Trade best bid / ask trading phase |
TRADE_AUCTION_NO_INDICATIVE |
Trade auction, but not indicative trading phase |
TradingPossibility
Trading possibility represents allowed variants to trade on specific stock exchange. Each trading possibility is a combination of the parameters. The list of the order possibilites is all possible combinations:
MARKET;NORMAL;ABSOLUTE;{KASSA;AUCTION} LIMIT;NORMAL;ABSOLUTE;{KASSA;AUCTION} MARKET;NORMAL;RELATIVE;{KASSA;AUCTION} LIMIT;NORMAL;RELATIVE;{KASSA;AUCTION} ...
| Field | Type | Description |
|---|---|---|
order_model |
Order model |
|
order_supplement |
Order supplement |
|
trailing_notation |
Trailing notation |
|
cash_quotations |
List of CashQuotation |
List of allowed cash_quatations |
TradingState
Trading state represents information about tradability. Security can be tradable or not (ex. index)
| Field | Description |
|---|---|
NO_TRADING_STATE |
Trading state is not defined |
TRADABLE |
Tradable state |
NOT_TRADABLE |
Not tradable state |
TrailingNotation
Trailing notation represent notation type by trailing orders
| Field | Description |
|---|---|
NO_TRAILING_NOTATION |
Trailing notation is not defined |
ABSOLUTE |
Absolute order notation |
RELATIVE |
Relative order notation |
Transaction
Transaction contains onformation about one transaction
| Field | Type | Description |
|---|---|---|
transaction_date |
Transaction date |
|
amount |
double |
Amount value |
opponent |
string |
Transaction opponent |
information |
string |
Information about transaction |
value_date |
Value date |
UnitNote
Unit node type
| Field | Description |
|---|---|
NO_UNIT_NOTE |
Unit note is not defined |
PIECE |
Piece unit note |
PERCENT |
Percent unit node. Pieces = Percent/100 |
PERMIL |
Permile unit node. Pieces = Percent/1000 |
POINTS |
Points unit node |
MISK |
Misk unit node |
Validation
Validation type for the order actions
| Field | Description |
|---|---|
WITHOUT_VALIDATION |
Order action will routed directly to the market. |
VALIDATE_ONLY |
Order will checked by the backend system, but not will be routed to market |
VALIDATE_WITH_TOTAL_COSTS |
Order will checked by the backend system, but not will be routed to market. Additionally will be requested estimated order action total costs. |
VALIDATE_WITH_DETAIL_COSTS |
Order will checked by the backend system, but not will be routed to market. Additionally will be requested estimated order action detail costs. |
TOTAL_COSTS_ONLY |
For the order will be requested estimated order action total costs. No backend system validation is processed. |
Questions and Answers
-
Why is used GRPC engine?
The GRPC is fastest engine for push and pull messaging with building security support. It allowes to reduce time for requests execution (ex. add order) and cares about low level communication.
-
Is will be supported another languages?
We delivery original protobuf protocol description. It can be used for the code generation for other programming languages like C++, Python, Go, Ruby, Node.js, Android Java, Objective-C, PHP, Dart and Web. For more information please refer to the grpc.io
-
Is it planned to extend TAPI?
If we see an interest from the customers to use additional functionality, then TAPI can be extended.
-
Where I can ask questions / get additional information about TAPI?
Please use next link or refer to the support team.