API Support Forum
User Profile

Viewing User Profile for: SRuscak


About

Aug 24, 2017 12:52 PM

Jan 07, 2021 03:38 PM

Jan 07, 2021 03:38 PM



Post Statistics
SRuscak has contributed to 40 posts out of 5029 total posts (0.80%) in 1245 days (0.00 posts per day).

20 most recent posts:

API Support » GAIN API COM Installer quirk Jan 07, 2021 @ 03:38 PM (Total replies: 1)

No, the behavior you see is correct :) It really is a quirk of the installer software we use, and nothing is supposed to happen. Sorry for the confusion.

API Support » Excel DOM example not working Jan 07, 2021 @ 03:30 PM (Total replies: 1)

Hello,

Yes, this code is pretty old. I improved the area around this function and it will be released in the next COM package.

SendLinkedOrders is no longer valid. You are looking for SendOSOOrders, and can see this in the C# documentation.
https://gainfutures.com/GFAPI/html/T_GF_Api_Orders_IOrdersApi.htm

Here is an improved VBA subroutine:

Sub SendOrder(side As OrderSide, row As Integer, qty As Integer)
On Error GoTo Err
Dim account As account
Set account = CurrentAccount
If account Is Nothing Then
MsgBox "Invalid account"
Else
Dim Price As Double
Price = CurrentTop - (row - TopRow) * CurrentContract.tickSize
If qty < 0 Then
DecreaseQty side, Price, -qty, account
Else
Dim Builder As OrderDraftBuilder
Set Builder = New OrderDraftBuilder
Builder.WithSide side
Builder.WithPrice Price
Builder.WithQuantity qty
Builder.WithContractID CurrentContract.id
Builder.WithComments "DOM"
Builder.WithAccountID account.id

If (side = OrderSide_Buy) And (Price CurrentContract.CurrentPrice.LastPrice) Then
Builder.WithOrderType (OrderType_Limit)
Else
Builder.WithOrderType (OrderType_Stop)
End If

Dim stopLoss As Integer
Dim takeProfit As Integer
Dim mainDraft As OrderDraft
Dim draftStopLoss As OrderDraft
Dim draftTakeProfit As OrderDraft

stopLoss = range("K6")
takeProfit = range("K7")
Set mainDraft = Builder.Build

If (stopLoss = 0) And (takeProfit = 0) Then
orders.SendOrder mainDraft
Else
If stopLoss 0 Then
If mainDraft.side = OrderSide_Buy Then
Builder.WithSide OrderSide_Sell
Builder.WithPrice mainDraft.Price - stopLoss * CurrentContract.tickSize
Else
Builder.WithSide OrderSide_Buy
Builder.WithPrice mainDraft.Price + stopLoss * CurrentContract.tickSize
End If
Builder.WithOrderType OrderType_Stop
Set draftStopLoss = Builder.Build
End If

If takeProfit 0 Then
If mainDraft.side = OrderSide_Buy Then
Builder.WithSide OrderSide_Sell
Builder.WithPrice mainDraft.Price + takeProfit * CurrentContract.tickSize
Else
Builder.WithSide OrderSide_Buy
Builder.WithPrice mainDraft.Price - takeProfit * CurrentContract.tickSize
End If
Builder.WithOrderType OrderType_Limit
Set draftTakeProfit = Builder.Build
End If

If (takeProfit 0) Then
If stopLoss 0 Then
orders.SendOSOOrders mainDraft, draftTakeProfit, draftStopLoss, OSOGroupingMethod_ByPrice
Else
orders.SendOSOOrders mainDraft, draftTakeProfit, Nothing, OSOGroupingMethod_ByPrice
End If
ElseIf stopLoss 0 Then
orders.SendOSOOrders mainDraft, draftStopLoss, Nothing, OSOGroupingMethod_ByPrice
End If
End If
End If
End If
Exit Sub
Err:
MsgBox Err.Description
End Sub


API Support » GAIN API COM installation and version query Jan 06, 2021 @ 12:50 PM (Total replies: 3)

Sorry, I was mistaken about item 1. You can use the "/verysilent" argument for this.

Order Execution » Getting real time position value Jan 06, 2021 @ 12:12 PM (Total replies: 1)

One change in GFAPI is that you need to subscribe to the contracts in the position in order to get an accurate position. Perhaps this is the issue?

Here is a sample for doing so: https://gainfutures.com/GFAPI/html/de577afb-edad-4021-a3cc-1fd943896903.htm

API Support » PriceTick vs SubscriptionTick Jan 06, 2021 @ 11:05 AM (Total replies: 1)

Hello.

Are you asking about the difference between price subscriptions and tick subscriptions?https://gainfutures.com/GFAPI/html/T_GF_Api_Subscriptions_Price_IPriceSubscriptionApi.htm https://gainfutures.com/GFAPI/html/T_GF_Api_Subscriptions_Ticks_ITicksSubscriptionApi.htm
A tick is something that you would put on a graph, representing the smallest time unit, while a price subscription will give you full price data.

Probably you want to call gfClient.Subscriptions.Price.Subscribe(contractID), and listen to the PriceTick or PriceChanged events. It may not give you price data every second, but prices don't update every second anyway. When the price changes, an event will be raised.

API Support » Procedure written using OEC API Jan 06, 2021 @ 10:37 AM (Total replies: 1)

I'm not sure if I have enough context to help you. What seems to be the issue?

I am wondering if this type is correct:
Dim ActiveOrder As GF_Api_COM.ordersApi

OrdersApi is an object that contains methods related to orders, not an order itself.
https://gainfutures.com/GFAPI/html/T_GF_Api_Orders_IOrdersApi.htm

API Support » GAIN API COM installation and version query Jan 06, 2021 @ 09:47 AM (Total replies: 3)

Hello,

1) No, there is currently no silent install option.

2) There is also no way to specify a different directory.

3) The version is in the dll File Version metadata, so you could programmatically inspect that.

We will keep these in mind for future development.

API Support » Runtime 13 Type Mismatch error - cancel All Jan 06, 2021 @ 08:07 AM (Total replies: 1)

Hello,

Probably you are getting a Type Mismatch error because you are passing a long instead of OrderID.
https://gainfutures.com/GFAPI/html/M_GF_Api_Orders_IOrdersApi_CancelOrder.htm

-Seth

API Support » Open position P/L issue Dec 02, 2020 @ 07:41 AM (Total replies: 9)

Mauro,

You are correct, this is a difference between OEC API and GF API. In GF API the client chooses how to use the limited number of subscriptions available to it.

API Support » Open position P/L issue Dec 01, 2020 @ 10:31 AM (Total replies: 9)

>GF API version is the very latest available with Gain Trader Developer 4.0.
I will note that there is no GF API available with Gain Trader. The public version we support is available on nuget: https://www.nuget.org/packages/GFAPI/

Market Data » LastDateTime is old Oct 14, 2020 @ 09:00 AM (Total replies: 3)

The DateTime is UTC, it's just that the DateTime.Kind is set to DateTimeKind.Unspecified when the message from the server is deserialized. But you are right, it would be more correct as DateTimeKind.Utc, and we plan to address this in a future release.

Market Data » LastDateTime is old Oct 13, 2020 @ 12:28 PM (Total replies: 3)

The time is already in UTC, so I suspect you just need to remove the ToUniversalTime call.

API Support » GAIN API COM Example problem Aug 05, 2020 @ 01:51 PM (Total replies: 2)

An update has been pushed to the comapisamples repo to fix x64 event argument references. Please try again.

API Support » GAIN API COM Example problem Jul 24, 2020 @ 11:46 AM (Total replies: 2)

Hello,

We have reproduced your issue. It looks like in x64, COM is not sending event arguments pointers correctly. We will investigate a fix.

Regarding 4b -- I suspect this is happening when you are debugging long enough that the API fails the heartbeat and disconnects.

API Support » Getting the "ConnectionError" when connecting to the Gain Futures server Jul 08, 2020 @ 07:41 AM (Total replies: 9)

Reusing a connection for multiple requests from the same user sounds like a good idea. You won't have to log in and initialize every time.

>This will avoid the bottleneck when I have to process requests sequentially per user as you mentioned above
The requests must be made on the GFAPI thread, therefore they will be sequential. But there is no need to wait for the response before sending another request.

>the callback event only processes one request at a time
Well, it processes one *response* at a time. When Advance is called by the GFAPI thread, it processes all requests and responses, including raising events if need be. If you make two requests, the server will return two responses and GFAPI will raise an event for each, when it arrives. The callback event args will contain enough information to identify the request that initiated it.

>I'm not sure that GF API works properly in case there are multiple requests made in the same login session and the subscribed callback events must handle all of them.
This is normal. Consider an application like Gain Trader https://gainfutures.com/gain-trader/. It uses a single GFAPI login session and executes many many requests.

API Support » Getting the "ConnectionError" when connecting to the Gain Futures server Jun 30, 2020 @ 01:20 PM (Total replies: 9)

The connection operates as a state machine. If it's already disconnected, there should be no need to disconnect again.

As for the client runner, I don't think there's any benefit in running it while the client is disconnected.

API Support » Getting the "ConnectionError" when connecting to the Gain Futures server Jun 29, 2020 @ 10:16 AM (Total replies: 9)

Internally, we use a client-per-application model, but I believe we do have clients that use a client-per-user model. As for a client-per-request model, one downside is that there is a significant chunk of initialization data that gets downloaded on every login. But more importantly, only one simultaneous login per user is allowed, so you would have to make requests sequential per-user.

Looking at your server logs, I see that there are some 'user already connected' errors. This could be because of the above issue, or because you aren't disconnecting after the request, or because you aren't using 'force login' in the connection context.

Connection can't be perfectly reliable, so maybe you should use a reconnection attempt strategy. I posted one here (https://apisupport.gainfutures.com/Topic/Index/1336), if you want to adapt it.

API Support » Getting the "ConnectionError" when connecting to the Gain Futures server Jun 26, 2020 @ 08:45 AM (Total replies: 9)

Creating a client per-request is not a use case we've designed for. Typically we expect a single instance that runs for the life of the application, which may connect and disconnect many times, even for different users. Your use case might work, but I can't be sure.

It looks to me that, in your code, after calling Aggregate.Connect the code does not wait for LoginComplete to fire before calling CreateSignal. Aggregate.Connect is not synchronous.

As for a side effect involving async/await... it may be possible. We will investigate and release a patch if something turns up.

API Support » Getting the "ConnectionError" when connecting to the Gain Futures server Jun 25, 2020 @ 02:52 PM (Total replies: 9)

Hello.

No, connection is working fine on our end.

>call the GF request inside a complex process
Do you mean the login request?

>inside a complex process
The problem may be thread timing. If you're not on the GFAPI thread, you should call Connect inside GF.Threading.Invoke. On the other hand, if the GFAPI thread is being hogged by a complex process, then Advance won't be called frequently enough to successfully log in.

API Support » IGFClient auto-reconnect problem Jun 25, 2020 @ 02:50 PM (Total replies: 1)

Hello, sorry to hear you're having difficulties with the connection code.

Solution #1

>await Task.Delay(5000);
This fails because the subsequent connection call is on some unknown thread, not the GFAPI thread.


Solution #2

It looks like in the last connection attempt from your screenshot, OnDisconnected wasn't called, so the reconnect code didn't run. Probably only OnLoginFailed was called. OnLoginFailed is another scenario where you may want to reconnect.


I wrote a reconnection solution for you, similar to what we use.

public class GFApiReconnecter
{
private IGFClient _client;
private CancellationTokenSource _cts;
private ConnectionContext _connectionContext;
private GF.Api.Utils.GFApiEventHandler _loginFailed;

public void Register(IGFClient client, GF.Api.Utils.GFApiEventHandler loginFailed)
{
_client = client;
_loginFailed = loginFailed;
client.Connection.Aggregate.LoginCompleted += (gfClient, args) => EndReconnect();
client.Connection.Aggregate.LoginFailed += (gfClient, args) =>
{
if (args.FailReason != GF.Api.Values.Users.FailReason.ConnectionError || _cts?.IsCancellationRequested != false)
{
EndReconnect();
_loginFailed(gfClient, args);
}
else
{
Reconnect();
}
};

client.Connection.Aggregate.Disconnected += (gfClient, args) =>
{
if (args.Reason != DisconnectionReason.SocketError || _cts?.IsCancellationRequested == false)
return;

_cts = new CancellationTokenSource();
Reconnect();
};
}

public void Connect(ConnectionContext context)
{
_connectionContext = context;
_client.Connection.Aggregate.Connect(context);
}

private void Reconnect()
{
if (_client.Connection.Aggregate.IsClosed)
{
_client.Threading.BeginDelayedInvoke(
TimeSpan.FromSeconds(1),
() => _client.Connection.Aggregate.Connect(_connectionContext),
_cts.Token);
}
}

private void EndReconnect()
{
_cts?.Cancel();
if (_client.Connection.Aggregate.IsConnecting)
_client.Connection.Aggregate.Disconnect();
}
}