Giter Club home page Giter Club logo

invest-openapi-csharp-sdk's Introduction

OpenAPI .NET SDK

Build NuGet version (Tinkoff Trading OpenApi) NuGet version (Tinkoff Trading OpenApi)

Данный проект представляет собой инструментарий на языке C# для работы с OpenAPI Тинькофф Инвестиции, который можно использовать для создания торговых роботов.

Рекомендуется использовать новый InvestApi SDK

Начало работы

Nuget

SDK доступен на nuget.org, для подключения добавьте в проект зависимость Tinkoff.Trading.OpenApi.

Сборка

Для сборки вам потребуется совместимая с .netstandard 2.0 реализация .NET. Перейдите в директорию проекта и выполните следующую команду:

dotnet build -c Release

Или с помощью docker

docker run --rm  -v "$PWD":/home/dotnet/project -w  /home/dotnet/project mcr.microsoft.com/dotnet/core/sdk:3.0 dotnet build -c Release

После успешной сборки в поддиректории bin/Release/netstandard2.0 появится файл Tinkoff.Trading.OpenApi.dll, который можно подключить к любому другому .NET-проекту.

Где взять токен аутентификации?

В разделе инвестиций вашего личного кабинета tinkoff . Далее:

  • Перейдите в настройки
  • Проверьте, что функция “Подтверждение сделок кодом” отключена
  • Выпустите токен для торговли на бирже и режима “песочницы” (sandbox)
  • Скопируйте токен и сохраните, токен отображается только один раз, просмотреть его позже не получится, тем не менее вы можете выпускать неограниченное количество токенов

Документация

Документацию непосредственно по OpenAPI можно найти по ссылке.

Быстрый старт

Для непосредственного взаимодействия с OpenAPI нужно создать подключение.

using Tinkoff.Trading.OpenApi.Network;
...
// токен аутентификации
var token = "my.token";
// для работы в песочнице используйте GetSandboxConnection
var connection = ConnectionFactory.GetConnection(token);
var context = connection.Context;

// вся работа происходит асинхронно через объект контекста
var portfolio = await context.PortfolioAsync();

У меня есть вопрос

Основной репозиторий с документацией — в нем вы можете задать вопрос в Issues и получать информацию о релизах в Releases. Если возникают вопросы по данному SDK, нашёлся баг или есть предложения по улучшению, то можно задать его в Issues.

invest-openapi-csharp-sdk's People

Contributors

0pd avatar ayratvv avatar dependabot[bot] avatar klarulor avatar nikitamelnikov avatar noviprog avatar olsh avatar rus-art avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

invest-openapi-csharp-sdk's Issues

Подскажите, как правильно пересоздавать сокет?

Проблема в том, что 1-2 раза в день WebSocketException возвращает ошибку из-за которой сокет переходит в состояние "Aborted", после чего было бы логично:
переподписаться на получение свечей и методы т.е. SendStreamingRequestAsync(StreamingRequest.UnsubscribeCandle()), и после StreamingRequest.SubscribeCandle() - но получаю ошибку "с# The WebSocket is in an invalid state ('Aborted') for this operation. Valid states are: 'Open, CloseReceived'"
Корректно ли в этом случае просто создать новое подключение таким образом ConnectionFactory.GetConnection(Token.work).Context?

Handle closed web socket connections

When a web socket connection is closed, the library doesn't notify a client about the event.
Therefore, it's very hard to implement a reconnection logic in apps.

Steps to reproduce:

  1. Subscribe to any event using SendStreamingRequestAsync
  2. Close the created WS connection using TcpView (you can use any other tool for this)

Expected result:
The library throws an exception or sends an event to a client or tries automatically reconnect to the server

Actual result:
The library does nothing

Ошибка Access Denied: You have no access to that resource

Продолжение темы Запуск простейшего примера на C#. GATEWAY_REQUEST_DATA_ERROR: Invalid token scopes.

Tinkoff.Trading.OpenApi.Network.OpenApiException: Access Denied: You have no access to that resource..
at Tinkoff.Trading.OpenApi.Network.Connection1.HandleResponseAsync[TOut](HttpResponseMessage response) at Tinkoff.Trading.OpenApi.Network.Connection1.SendGetRequestAsync[TPayload](String path)
at Tinkoff.Trading.OpenApi.Network.Context.PortfolioAsync(String brokerAccountId)
at TinkoffTradingRobot.Program.Run(String[] args) in F:\Programming\C#\WORK\TinkoffTradingRobot\TinkoffTradingRobot\Program.cs:line 33

Код:

using System;
using System.Threading.Tasks;
using Tinkoff.Trading.OpenApi.Network;

namespace TinkoffTradingRobot
{
    class Program
    {
        private static Program _program;

        private static Task Main(string[] args)
        {
            _program = new Program();
            return _program.Run(args);
        }

        private async Task Run(string[] args)
        {
            // токен аутентификации
            string token = "Токен сгенерировал по инстукции. Это Sandbox.";

            // для работы в песочнице используйте GetSandboxConnection
            var connection = ConnectionFactory.GetConnection(token);
            using var context = connection.Context;
            try
            {
                // вся работа происходит асинхронно через объект контекста
                var portfolio = await context.PortfolioAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            Console.ReadKey();
        }
    }
}

OperationsAsync падает на десериализации

Вызов:

await context.OperationsAsync(new DateTime(2019, 10, 10), Interval.Day, "BBG00B52KN20");

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List1[Tinkoff.Trading.OpenApi.Models.Operation]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'payload.operations', line 1, position 57. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor1 creator, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Tinkoff.Trading.OpenApi.Network.Connection1.HandleResponseAsync[TOut](HttpResponseMessage response) in C:\Z\projects\invest-openapi-csharp-sdk\src\Tinkoff.Trading.OpenApi\Network\Connection.cs:line 78 at Tinkoff.Trading.OpenApi.Network.Connection1.SendGetRequestAsync[TPayload](String path) in C:\Z\projects\invest-openapi-csharp-sdk\src\Tinkoff.Trading.OpenApi\Network\Connection.cs:line 42
at Tinkoff.Trading.OpenApi.Network.Context.OperationsAsync(DateTime from, Interval interval, String figi) in C:\Z\projects\invest-openapi-csharp-sdk\src\Tinkoff.Trading.OpenApi\Network\Context.cs:line 102

Улучшить метод market/candles ( MarketCandlesAsync )

Очень неудобно использовать даты в методе, это не datetimeoffset, это не unix timestamp, плюс можно сделать метод более удобным.

Для примера: можно попробовать в 3 ночи получить данные за вчера 5мин интервалом за день,
что всего 21 свеча хммм ... (from: DateTime.Now.Date.AddDay(-1), to: DateTime.Now.Date), смотришь все вроде верно хотел получить данные с 2020-12-02 до 2020-12-03 но вот не судьба.

в итоге пришел к такому методом подбора:
высчитыввать свое отклонение (+3) и просить данные с 7 утра до 23:59.

await tsDs.LoadData("ticker",
DateTime.Parse("2020-12-02T07:00:00"),
DateTime.Parse("2020-12-02T23:59:00"),
(int)Models.CandleInterval.FiveMinutes);

Данные получаем с 7 утра до 8:55 вечера (опять же почему не вернуть даты с отклонением неизвестно),
при том что торги по инструменту идут с 10 утра до 01.30 ночи,
шаг влево в право ошибка.

Примеры как бы хотелось уметь:

Взять данные за часть дня/день используя либо datetime offset либо unix temestamp используя:

[EnumMember(Value = "1min")] Minute,
[EnumMember(Value = "2min")] TwoMinutes,
[EnumMember(Value = "3min")] ThreeMinutes,
[EnumMember(Value = "5min")] FiveMinutes,
[EnumMember(Value = "10min")] TenMinutes,
[EnumMember(Value = "15min")] QuarterHour,
[EnumMember(Value = "30min")] HalfHour,
[EnumMember(Value = "hour")] Hour,

Взять данные за определенный день (гг-мм-дд) используя:

[EnumMember(Value = "1min")] Minute,
[EnumMember(Value = "2min")] TwoMinutes,
[EnumMember(Value = "3min")] ThreeMinutes,
[EnumMember(Value = "5min")] FiveMinutes,
[EnumMember(Value = "10min")] TenMinutes,
[EnumMember(Value = "15min")] QuarterHour,
[EnumMember(Value = "30min")] HalfHour,
[EnumMember(Value = "hour")] Hour,

Взять данные за определенную неделю (по номеру, указывая календарь американский или русский) используя

[EnumMember(Value = "day")] Day,
[EnumMember(Value = "hour")] Hour,

Взять данные за месяц указывая год и номер месяца используя:

[EnumMember(Value = "day")] Day,
[EnumMember(Value = "week")] Week,

Взять данные за год используя :

[EnumMember(Value = "day")] Day,
[EnumMember(Value = "week")] Week,
[EnumMember(Value = "month")] Month,

Sdk C# _ START

Добрый день! Помогите пл..
using Tinkoff.Trading.OpenApi.Network;
...
// токен аутентификации
var token = "my.token";
// для работы в песочнице используйте GetSandboxConnection
var connection = ConnectionFactory.GetConnection(token);
var context = connection.Context;

// вся работа происходит асинхронно через объект контекста
var portfolio = await context.PortfolioAsync();

Правильно ли  понял: переменной token присваиваю свой тукен 
а всё остальное уже прописано в sdk (url,wc и т.д) 

portfolio  надо распарсивать ????  Возвращается в формате Json ???

Не могу понять как вывести для просмотра ...
Можно пример для С# 
C nodejs  разобрался, а вот в C# никак ..

За ранее спасибо. 

Не исполняется рыночная заявка PlaceMarketOrderAsync: RejectedReason = Unknown

В момент совершения рыночной заявки система возвращает response.RejectReason = 'Unknown'. Как понять почему не исполнилась заявка?

        public async void DoMarketOrder(OperationType operationType)
        {
            var response = await _context.PlaceMarketOrderAsync(new MarketOrder(figi, int.Parse(tbLots.Text), operationType, _accountId));
            WriteLog(operationType.ToString() + " " + tbLots.Text + " " + cbInstrument.Text + " " + response.Status.ToString() + " " + response.RejectReason);
        }

image
Могло ли повлиять то, что заявку выставлял после 23:00?

Error converting value "JPY" to type 'Tinkoff.Trading.OpenApi.Models.Currency'.

Starting from today, I get the issue when trying to call PortfolioCurrenciesAsync method.

Here is a code which triggers the error:

var token = "token";
var connection = ConnectionFactory.GetConnection(token);
var context = connection.Context;

var currencies = await context.PortfolioCurrenciesAsync();

// Print currencies here
currencies.Dump();

Here is the full stack trace:

   at Newtonsoft.Json.Converters.StringEnumConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
   at Tinkoff.Trading.OpenApi.Network.Connection`1.<HandleResponseAsync>d__14`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Tinkoff.Trading.OpenApi.Network.Connection`1.<SendGetRequestAsync>d__11`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Tinkoff.Trading.OpenApi.Network.Context.<PortfolioCurrenciesAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
--

I believe this enum should be extended with the new currencies.

https://github.com/TinkoffCreditSystems/invest-openapi-csharp-sdk/blob/286a44a9c6fa1e0a2030f1334df3b08226e01d09/src/Tinkoff.Trading.OpenApi/Models/Currency.cs#L10-L12

Improve JSON deserialization exception handling

Sometimes the REST API server returns something, but not a JSON.
In this cases the deserialization fails here:
https://github.com/TinkoffCreditSystems/invest-openapi-csharp-sdk/blob/286a44a9c6fa1e0a2030f1334df3b08226e01d09/src/Tinkoff.Trading.OpenApi/Network/Connection.cs#L71-L86

And in your stack traces you get an unclear error, something like that:

Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: S. Path '', line 0, position 0.
  Module "Newtonsoft.Json.JsonTextReader", in ParseValue
  Module "Newtonsoft.Json.JsonReader", in ReadForType
  Module "Newtonsoft.Json.Serialization.JsonSerializerInternalReader", in Deserialize
  Module "Newtonsoft.Json.JsonSerializer", in DeserializeInternal
  Module "Newtonsoft.Json.JsonConvert", in DeserializeObject
  Module "Newtonsoft.Json.JsonConvert", in DeserializeObject
  Module "Tinkoff.Trading.OpenApi.Network.Connection`1+<HandleResponseAsync>d__14`1", in MoveNext
  Module "System.Runtime.ExceptionServices.ExceptionDispatchInfo", in Throw
  Module "System.Runtime.CompilerServices.TaskAwaiter", in ThrowForNonSuccess
  Module "System.Runtime.CompilerServices.TaskAwaiter", in HandleNonSuccessAndDebuggerNotification
  Module "Tinkoff.Trading.OpenApi.Network.Connection`1+<SendGetRequestAsync>d__11`1", in MoveNext
  Module "System.Runtime.ExceptionServices.ExceptionDispatchInfo", in Throw
  Module "System.Runtime.CompilerServices.TaskAwaiter", in ThrowForNonSuccess
  Module "System.Runtime.CompilerServices.TaskAwaiter", in HandleNonSuccessAndDebuggerNotification
  Module "Tinkoff.Trading.OpenApi.Network.Context", in OrdersAsync
  Module "System.Runtime.ExceptionServices.ExceptionDispatchInfo", in Throw
  Module "System.Runtime.CompilerServices.TaskAwaiter", in ThrowForNonSuccess
  Module "System.Runtime.CompilerServices.TaskAwaiter", in HandleNonSuccessAndDebuggerNotification

It would be nice to see the real error or raw response, at least.

Заменить Newtonsoft.Json на System.Text.Json

Было бы неплохо мигрировать с Newtonsoft.Json на System.Text.Json

https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?pivots=dotnet-5-0

  • Newtonsoft.Json перешел в maintenance mode и не будет активно развиваться. В то время как System.Text.Json активно развивается и поддерживается MicroSoft
  • System.Text.Json быстре чем Newtonsoft.Json (производительность стала еще лучше в .NET 5.0)
  • Начиная с .NET Core 3.1 System.Text.Json входит в стандартные зависимости

Add examples

Implement an example of a simple trading robot.

Context.OperationsAsync кидает неинформативное исключение OpenApiException: INTERNAL_ERROR.

Часто при запросе OperationsAsync возвращается неинформативный OpenApiException: INTERNAL_ERROR:

---> Tinkoff.Trading.OpenApi.Network.OpenApiException: INTERNAL_ERROR: INTERNAL_ERROR (a715629199c52eb5).
at async Task Tinkoff.Trading.OpenApi.Network.Connection.HandleResponseAsync(HttpResponseMessage response) in ../Tinkoff.Trading.OpenApi/src/Tinkoff.Trading.OpenApi/Network/Connection.cs:line 118
at async Task Tinkoff.Trading.OpenApi.Network.Connection.SendGetRequestAsync(string path) in ../Tinkoff.Trading.OpenApi/src/Tinkoff.Trading.OpenApi/Network/Connection.cs:line 49
at async Task Tinkoff.Trading.OpenApi.Network.Context.OperationsAsync(DateTime from, DateTime to, string figi, string brokerAccountId) in ../Tinkoff.Trading.OpenApi/src/Tinkoff.Trading.OpenApi/Network/Context.cs:line 158

Необходимо уменьшить процент ошибок при запросе и/или добавить больше информации о причине исключения.

PlaceLimitOrderAsync

Добрый день,

устанавливаю в песочнице себе баланс (все по 99 уе):

await context.SetCurrencyBalanceAsync(Tinkoff.Trading.OpenApi.Models.Currency.Rub, 99);
await context.SetCurrencyBalanceAsync(Tinkoff.Trading.OpenApi.Models.Currency.Usd, 99);
await context.SetPositionBalanceAsync("BBG0013HGFT4", 99);

но при попытке поставить заявку на покупку пишет НЕТ денег

PlacedLimitOrder placedLimitOrder = await context.PlaceLimitOrderAsync(new LimitOrder("BBG0013HGFT4", 1, OperationType.Buy, 1));

NOT_ENOUGH_BALANCE: Cannot process request, not enough balance on security=RUB (da9daa52f8eb6dd1).

Можете сказать в чем дело?

IContext.PortfolioAsync don't provide brokerAccountId

Ru

Добрый день. Метод IContext.PortfolioAsync похоже отсырел, т.е. не принимает brokerAccountId. В swagger этот параметр есть.

Кстати, откуда brokerAccountId можно взять?

En

Hi. The IContext.PortfolioAsync method looks very old, i.e. don't accepts brokerAccountId. In swagger this parameter is.

By the way, where can I get brokerAccountId?

Ошибка при десериализации InstrumentInfoPayload

Для инструмента BBG000RG4ZQ4 при десериализации InstrumentInfoPayload возникает исключение
System.Text.Json.JsonException: 'The JSON value could not be converted to Tinkoff.Trading.OpenApi.Models.InstrumentInfoPayload. Path: $.lot | LineNumber: 0 | BytePositionInLine: 94.'
FormatException: Either the JSON value is not in a supported format, or is out of bounds for an Int32.

При этом сам payload содержит
{"figi":"BBG000RG4ZQ4","trade_status":"normal_trading","min_price_increment":1e-05,"lot":1e+06}

image

При запросе /sandbox/market/candles в ответ попадают свечи вне from-to

При запросе /sandbox/market/candles по некоторым инструментам в ответ попадают свечи вне интервала from-to, пример:

https://api-invest.tinkoff.ru/openapi/sandbox/market/candles?figi=BBG004S689R0&from=2020-05-23T00%3A00%3A00%2B03%3A00&to=2020-06-02T23%3A59%3A59%2B03%3A00&interval=day. Response code: 200 {"queryData":{"figi":"BBG004S689R0","from":"2020-05-23T00:00:00+03:00","to":"2020-06-02T23:59:59+03:00","interval":"day"},"postData":[],"response":{"trackingId":"9c1c1e960e7fd515","payload":{"candles":[{"o":2789,"c":2796,"h":2813,"l":2760,"v":58604,"time":"2020-05-25T07:00:00Z","interval":"day","figi":"BBG004S689R0"},{"o":2795,"c":2800,"h":2825,"l":2783,"v":78984,"time":"2020-05-26T07:00:00Z","interval":"day","figi":"BBG004S689R0"},{"o":2801,"c":2812,"h":2833,"l":2797,"v":59433,"time":"2020-05-27T07:00:00Z","interval":"day","figi":"BBG004S689R0"},{"o":2805,"c":2875,"h":2880,"l":2805,"v":120497,"time":"2020-05-28T07:00:00Z","interval":"day","figi":"BBG004S689R0"},{"o":2860,"c":2788,"h":2893,"l":2785,"v":144775,"time":"2020-05-29T07:00:00Z","interval":"day","figi":"BBG004S689R0"},{"o":2786,"c":2802,"h":2819,"l":2724,"v":100129,"time":"2020-06-01T07:00:00Z","interval":"day","figi":"BBG004S689R0"},{"o":2816,"c":2819,"h":2830,"l":2787,"v":52576,"time":"2020-06-02T07:00:00Z","interval":"day","figi":"BBG004S689R0"},{"o":2819,"c":2819,"h":2819,"l":2819,"v":7,"time":"2020-06-03T07:00:00Z","interval":"day","figi":"BBG004S689R0"}],"interval":"day","figi":"BBG004S689R0"},"status":"Ok"},"time_ms":45} []

Context.OperationsAsync кидает исключение "OpenApiInvalidResponseException: Unable to handle response" с пустым Response.

Метод Context.OperationsAsync кидает исключение "OpenApiInvalidResponseException: Unable to handle response" (см ниже). При этом Response пустой.

 _---> Tinkoff.Trading.OpenApi.Network.OpenApiInvalidResponseException: Unable to handle response.
Response:

 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at async Task<OpenApiResponse<TOut>> Tinkoff.Trading.OpenApi.Network.Connection<TContext>.HandleResponseAsync<TOut>(HttpResponseMessage response)
   --- End of inner exception stack trace ---
   at async Task<OpenApiResponse<TOut>> Tinkoff.Trading.OpenApi.Network.Connection<TContext>.HandleResponseAsync<TOut>(HttpResponseMessage response)
   at async Task<OpenApiResponse<TPayload>> Tinkoff.Trading.OpenApi.Network.Connection<TContext>.SendGetRequestAsync<TPayload>(string path)
   at async Task<List<Operation>> Tinkoff.Trading.OpenApi.Network.Context.OperationsAsync(DateTime from, DateTime to, string figi, string brokerAccountId)_

OperationsAsync стал неверно возвращать время. (+2 часа)

Посылаю c.OperationsAsync(from,to) , Где From и To имеют DateTimeKind = Local.

Получаю [0].Date = {2021-03-26 02:03:39} [Local] , хотя это совершенно не верно. Правильно время {2021-03-26 00:03:39} [Local] . Заметил ориентировочно 24го марта. Скорее всего проблема на сервере.

Расхождение кол-ва купленных инструментов в Operations и Trades

Получаю сделки по инструменту методом OperationsAsync()

В объекте Operation поле Quantity равно 4-м, в коллекции Trades этого же объекта Operation, значение Quantity равно 2-м. Кол-во объектов в коллекции Trades - 1. При этом Payment в Operation имеет корректное значение.

Скрины

https://prnt.sc/11qqnur
https://prnt.sc/11qqotk

Кол-во операций в этот день - 1 (проверил по терминалу). Судя по всему оперировать надо данными из коллекции Trades объекта Operation.

Версия SDK 1.7.3

Получение цены бумаги в реальном времени через websocket/streaming

Добрый день!

Помогите, пожалуйста, мне нужен простой пример на C#, в котором бы организовывалась подписка (subscribe, если правильно называю и применяю данный термин) на событие изменения последней цены по заданной бумаге. Как организовывать такую подписку? Как вешать обработчик?

Смотрю пример кода, но тяжело разобраться(это единственный пример по streaming в данном sdk, не уверен, что он вообще подходит для данной темы):

StreamingResponseTests.cs

using System;
using FluentAssertions;
using Newtonsoft.Json;
using Tinkoff.Trading.OpenApi.Models;
using Tinkoff.Trading.OpenApi.Tests.TestHelpers;
using Xunit;
namespace Tinkoff.Trading.OpenApi.Tests
{
    public class StreamingResponseTests
    {
        [Fact]
        public void DeserializeCandleTest()
        {
            var streamingResponse = JsonConvert.DeserializeObject<StreamingResponse>(JsonFile.Read("streaming-candle-response"));
            var response = streamingResponse as StreamingResponse<CandlePayload>;
            var expectedResponse = new CandleResponse(
                new CandlePayload(
                    64.0575m,
                    64.0578m,
                    64.0579m,
                    64.0573m,
                    156,
                    new DateTime(2019, 08, 07, 15, 35, 00, DateTimeKind.Utc),
                    CandleInterval.FiveMinutes,
                    "BBG0013HGFT4"),
                new DateTime(2019, 08, 07, 15, 35, 01, 029, DateTimeKind.Utc).AddTicks(7213));
            response.Should().BeEquivalentTo(expectedResponse);
        }
    }
}

Я хочу получать данные о цене бумаги в реальном времени, т.е. HTTP протокол мне не очень подходит, т.к. нужно каждую секунду(или чаще) отправлять самому запрос на сервер и получать ответ, т.е. примерно так:

var orderbook = await _context.MarketOrderbookAsync(figi, 0);
this.lbPrice.BeginInvoke((MethodInvoker)(() => this.lbPrice.Text = orderbook.LastPrice.ToString()));

Как преобразовать этот код в Streaming API протокол, чтобы при изменении цены бумаги в реальном времени сервер сам дергал нужную функцию на клиенте? (естественно, очень грубо и некорректно описал смысл, но если расписывать правильно, займет много места. В общем нужен пример организации взаимодействия с сервером через websocket-ы).
Спасибо!

[Bug] MarketSearchByFigiAsync doesn't work

Hi,

Function MarketSearchByFigiAsync doesn't work. When I try to get instrument by its Figi, it doesn't exist. Maybe I don't get something.

Repro steps for the issue:

var instruments = await connection.Context.MarketSearchByTickerAsync("MSFT");
var instrumentsByFigi = await connection.Context.MarketSearchByFigiAsync(instruments.Instruments[0].Figi);

Expected:
instruments contains one instrument, instrumentsByFigi contains the same instrument as in instruments

Actual:
instruments contains one instrument, instrumentsByFigi doesn't contain any

MarketCandlesAsync(): Неверный формат поля 'from' в запросе

        var connection = ConnectionFactory.GetSandboxConnection(sandboxToken);
        var context = connection.Context;
        var from = new DateTime(2020, 3, 19, 10, 0, 0);
        var to = new DateTime(2020, 3, 19, 17, 59, 59);

        var marketCandles = context.MarketCandlesAsync("BBG004731489", from, to, CandleInterval.Minute)
            .Result
            .Candles;

OpenApiException: MALFORMED_QUERY_PARAMETER: Неверный формат поля 'from' в запросе (a6df22e00b1194bf).

So?)

GATEWAY_REQUEST_DATA_ERROR: Unknown account(....)

При попытке получить портфель из песочницы следующим образом:

 var connection = ConnectionFactory.GetSandboxConnection(sandboxToken);
 var context = connection.Context;
var portfolio = await context.PortfolioAsync();

Вываливается исключение GATEWAY_REQUEST_DATA_ERROR: Unknown account(....). Так и должно быть? С продакшеном все ок.

Подписка на orderbook

Написал простое WPF приложение, которое подписывается на стриминг данных. Однако исключения не срабатывают, debug.writeline ничего не выводит. Такое же приложение, но консольное, работает без проблем. В чем может быть проблема?

using System;
using System.Threading.Tasks;
using System.Windows;
using System.Threading;
using Tinkoff.Trading.OpenApi.Models;
using Tinkoff.Trading.OpenApi.Network;
using static Tinkoff.Trading.OpenApi.Models.StreamingRequest;
using System.Diagnostics;

namespace TinkoffWPF
{
///


/// Логика взаимодействия для MainWindow.xaml
///

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void cmdSubscribe_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => Subscribe());
}
private void Subscribe()
{
var sandboxToken = "t";
var connection = ConnectionFactory.GetSandboxConnection(sandboxToken);
var context = connection.Context;
context.StreamingEventReceived += Context_StreamingEventReceived;
string figi = "BBG000B9XRY4";
int depth = 2;
var orderbookSubscribeRequest = new OrderbookSubscribeRequest(figi, depth);
var orderbookUnsubscribeRequest = new OrderbookUnsubscribeRequest(figi, depth);
context.SendStreamingRequestAsync(orderbookSubscribeRequest);
}

    private static void Context_StreamingEventReceived(object sender, StreamingEventReceivedEventArgs e)
    {
        Debug.WriteLine("exception");    
    }
}

}

получение элемента графика сайта

есть ли какой-то запрос, который получает идентичную картину сайту?
В свечах абсолютно другие значения, а хотелось бы сравнивать стратегию с сайтом.
Скорее всего я просто не понимаю, как формируется цена из Open Close High Low, но все же, буду рад ответу))

скрин прилагаю
image

MarketOrderbookAsync does not work in the evening

Добрый день, метод MarketOrderbookAsync перестает работать для иностранных акций примерно с 23:00 и вплоть до окончания торгов.

Program just stops executing on context.PortfolioAsync() without errors

using Tinkoff.Trading.OpenApi.Network;
...
// токен аутентификации
var token = "мой супер токен";

var connection = ConnectionFactory.GetConnection(token);
var context = connection.Context;

// вся работа происходит асинхронно через объект контекста
var portfolio = await context.PortfolioAsync();

Инструкции расположенные ниже по коду не выполняются. Программа именно вылетает. Ошибок не выплёвывает. В чем дело, подскажите плиз

Orderbook and Candles in Context. C#

Добрый день. Подскажите пожалуйста, не нашел методов для получения истории по стакану и свечам в классе Context пространства Tinkoff.Trading.OpenApi.Network. В пространстве Tinkoff.Trading.OpenApi.Models есть классы CandlePayload, CandleInterval, OrderbookPayload, OrderbookResponse, но как эти объекты получить для необходимого инструмента, зная его FIGI или Ticker?

Невозможно подписаться на события получения стакана или свечей более чем на одну бумагу в одном соединении

Добрый день! Обнаружил, что при подписке на события получения стакана или свечей по веб сокетам невозможно получить данные по нескольким бумагам, только одна бумага на один Context. При подписке на еще на какие то бумаги (через метод SendStreamingRequestAsync) - приходит информация только по первой, остальные игнорируются. Не нашел нигде в документации описания о таких ограничениях. Это бага или все же фича? ) Спасибо!

Запуск простейшего примера на C#. GATEWAY_REQUEST_DATA_ERROR: Invalid token scopes.

Здравствуйте. Изначально была ошибка такая. Пусть будет здесь решение, пригодится кому-нибудь. Всё сделал по инструкции, запускаю приложение и вижу ошибку:

Tinkoff.Trading.OpenApi.Network.OpenApiException: GATEWAY_REQUEST_DATA_ERROR: Invalid token scopes (c8de689d4a5e2b60).
at Tinkoff.Trading.OpenApi.Network.Connection1.HandleResponseAsync[TOut](HttpResponseMessage response) at Tinkoff.Trading.OpenApi.Network.Connection1.SendGetRequestAsync[TPayload](String path)
at Tinkoff.Trading.OpenApi.Network.Context.AccountsAsync()
at TinkoffTradingRobot.Program.Run(String[] args) in F:\Programming\C#\WORK\TinkoffTradingRobot\TinkoffTradingRobot\Program.cs:line 31

Удалил из токена в начале "t.". Про то, что это нужно сделать нигде не написано.

Код:

using System;
using System.Threading.Tasks;
using Tinkoff.Trading.OpenApi.Network;

namespace TinkoffTradingRobot
{
    class Program
    {
        private static Program _program;

        private static Task Main(string[] args)
        {
            _program = new Program();
            return _program.Run(args);
        }

        private async Task Run(string[] args)
        {
            // токен аутентификации
            string token = "Токен сгенерировал по инстукции. Это Sandbox.";

            // для работы в песочнице используйте GetSandboxConnection
            var connection = ConnectionFactory.GetConnection(token);
            using var context = connection.Context;
            try
            {
                // вся работа происходит асинхронно через объект контекста
                var portfolio = await context.PortfolioAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            Console.ReadKey();
        }
    }
}

Получить цену закрытия | текущую

На текущий момент стоимость закрытия|текущую можно получить только со свечей вручную?
моё текущее решение: https://pastebin.com/vbTizzPi - не учитывает долларовые русские акции(TCS), можно ли узнать на каком рынке продаётся акция?

И есть ли более элегантное решение?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.