Comments (29)
Ок. У меня в БКС сейчас роботом торгуется более 250 акций. Я вот пытаюсь переписать на ваше апи.
Мне как минимум надо получить по каждой из них статус и стакан :) И вообще как можно роботу ставить ограничения по получению данных? :) Вы же понимаете, что ограничения должны идти в рамках инструмента (или другого объекта), а не в целом по API Call :)
Очень рекомендую поставить лимиты на 120 API CALL по инструменту, а не по рынку в целом :)
from invest-openapi-java-sdk.
Ну и как минимум 429 статус надо в обработке ContextImpl::handleResponse добавить
from invest-openapi-java-sdk.
Псевдо пример хороший. Только из стрима до этого уровня прослойки не хватает в SDK. Надо Executor курочить)
И очень не хватает стрима по Orders и Portfolio для полной картины :)
from invest-openapi-java-sdk.
Интересный кейс. Попробуем для начала воспроизвести.
from invest-openapi-java-sdk.
Кейс легко воспроизводится запуском получения стакана по списку акций context.getMarketOrderbook(i.getFigi(),1).join();
более 150 раз (разных акций) в цикле (как на примере)
from invest-openapi-java-sdk.
java.util.concurrent.CompletionException: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
at [Source: (String)""; line: 1, column: 0]
at java.base/java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:367)
at java.base/java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:376)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1074)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:610)
at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:840)
at java.base/java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:479)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
at [Source: (String)""; line: 1, column: 0]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:4145)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4000)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3023)
at ru.tinkoff.invest.openapi.wrapper.impl.ContextImpl.handleResponse(ContextImpl.java:326)
at ru.tinkoff.invest.openapi.wrapper.impl.ContextImpl.lambda$sendGetRequest$17(ContextImpl.java:288)
at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1072)
... 9 more
from invest-openapi-java-sdk.
В openapi добавлен rate limiting: https://tinkoffcreditsystems.github.io/invest-openapi/rest/
На весь market сейчас 120 запросов в минуту
from invest-openapi-java-sdk.
Мне как минимум надо получить по каждой из них статус и стакан :)
Как часто вы обновляете данные и какой у вас кейс?
Вы же понимаете, что ограничения должны идти в рамках инструмента (или другого объекта), а не в целом по API Call
Совсем не обязательно, рейтлимиты идут по ресурсу + по клиенту.
У нас в планах разделить лимиты по market/candles, market/orderbook и остальные, но вряд ли мы будем ставить рейты по каждому инструменту отдельно.
Как временное решение поднимем рейт-лимиты до 400 RPM
from invest-openapi-java-sdk.
Так как у вас стратегии сейчас не работают логика работы в цикле у робота такая
- взять портфель (200+ инструментов). For each{
- получить стакан (для статуса и last price)
- если статус боевой - получить Orders
- Если Order есть - проверит не пора ли снимать и снять
- Если Order нет - проверит пора ли ставить и выставить
}
-
Найти все акции которые не в портфеле и на которые нет Orders (да да, опять API Calls). Произвести закупку если есть свободные средства (API Call пересчитанных средств с учетом блокировок после каждого выставленного Order).
-
По кругу раз в минуту.
Как видно тут много API Call. QUIK + lua без вопросов с такой задачей справляется :)
from invest-openapi-java-sdk.
Так как у вас стратегии сейчас не работают логика работы в цикле
Это пример стратегии, его не нужно использовать для запуска :)
на которые нет Orders (да да, опять API Calls).
Это будут разные лимиты https://tinkoffcreditsystems.github.io/invest-openapi/rest/
from invest-openapi-java-sdk.
Это будут разные лимиты https://tinkoffcreditsystems.github.io/invest-openapi/rest/
И все же мне по каждому инструменту в портфеле или в маркете надо получить "есть ли заявки", а потом произвести снятие заявки и/или выставление. Это в максимуме получается по 3 API CALL на инструмент.
from invest-openapi-java-sdk.
И все же мне по каждому инструменту в портфеле или в маркете надо получить "есть ли заявки",
val orders = getOrders() // limits.orders == 1
val portfolio = getPortfolio() // limits.portfolio == 1
orders.foreach { order =>
if (...) {
cancelAndPlaceORder() // limits.orders += 2
}
}
Итого в максимуме мы получаем:
1 лимит в портфелях
portfolio.positions.count * 3
лимитов в ордерах, если по каждой позиции есть заявка
При этом у биржи так же есть ограничение на количество операций на клиента
from invest-openapi-java-sdk.
Опять же, в маркет ходить не обязательно, так как есть стриминг-протокол :)
from invest-openapi-java-sdk.
-
В данном примере нет влияния результатов выполнения ордеров.
Пока выполняется прогнока по одним инструментам, то могут быть изменения по портфелю или исполнения по ордерам. Получится не корректная работа робота. Робот должен принимать решение на основании фактических текущих данных. Для этого перед принятием решения об изменениях он должен получить актуальные данные.
Реализовывать кеш на клиенте самостоятельно это ад :) У вас есть события по изменениям. Кешируйте на беке ответ пока событие по ордеру или инструменту об обновлении не прилетело, в чем проблема?
portfolio.positions.count * 3 лимитов в ордерах, если по каждой позиции есть заявка
плюс ордера по маркету которые еще не попали в портфель, т.к. ордер не исполнился.
from invest-openapi-java-sdk.
Опять же, в маркет ходить не обязательно, так как есть стриминг-протокол :)
Отлично было бы пример его использования в основном коде без использования стратегии.
По сути если бы по простому можно было подписаться по инструменту типа:
context.newSubscirbe(Intrument, new () {
@override onChangeOrder (Order o){
}
@override onChangePortfolio (BlaBla o){
}
})
В StrategyExecuter как пример использовать сложно, там логики "сверху" много.
from invest-openapi-java-sdk.
Я с вами полностью согласен,
Робот должен принимать решение на основании фактических текущих данных.
И этим данные есть в стриминге
Кешируйте на беке ответ пока событие по ордеру или инструменту об обновлении не прилетело, в чем проблема?
Проблемы в этом нет, есть проблема в неконтролируемом потоке запросов к REST для случаев, когда существует streaming.
from invest-openapi-java-sdk.
Отлично было бы пример его использования в основном коде без использования стратегии.
Возможно дело не в рейт-лимитах, а в неполноте документации как правильно использовать openapi и для каких случаев нужен REST?
Давайте попробуем описать ваш алгоритм словами, а я попробую сформулировать как это ложится на наш протокол? И посчитаем, хватает ли лимитов
from invest-openapi-java-sdk.
По протоколу все понятно. Вопросы больше к SDK. Сейчас streaming реализован в StrategyExecutor. А он не работает как пример с множеством инструментов. Как без него подписаться в SDK на поток не понятно, примеров нет. Если работать в лоб без потоков - упираешся в лимиты.
from invest-openapi-java-sdk.
Давайте попробуем описать ваш алгоритм словами, а я попробую сформулировать как это ложится на наш протокол? И посчитаем, хватает ли лимитов
Давайте. По сути мне при каждом изменении по инструментам из портфеля для принятия решения робота надо понимать:
- Есть ли активные ордера
- Текущие позиции по этому инструменту в портфеле
- Стакан, цена и статус
- Что общим балансом и свободными средствами на данный момент
Плюс по инструментам не в портфеле в случае наличия свободных средств:
- Есть ли активные ордера
- Стакан, цена и статус
- Что общим балансом и свободными средствами на данный момент
from invest-openapi-java-sdk.
А как вы выбираете инструмент, которого нет в портфеле, для торгов?
from invest-openapi-java-sdk.
Беру список акции (простые не привилегированные) ММВБ. Сортирую по Level ASC + Price DESC. Закупаю пока есть средства Рыночным ордером на количество примерно на Х рублей.
Если на рынке ММВБ все купил (а сейчас именно так), то иду в акции СПБ. Алгоритм тот же.
from invest-openapi-java-sdk.
В StrategyExecuter как пример использовать сложно, там логики "сверху" много.
Согласен. Откровенно говоря, на проработку StrategyExecutor уделялось мало времени и внимания, и это планируется исправить в ближайшем релизе.
Ваш схематичный пример
context.newSubscirbe(Intrument, new () {
@override onChangeOrder (Order o){
}
@override onChangePortfolio (BlaBla o){
}
})
очень приглянулся. Допускаю, что это станет ориентиром при переработке StrategyExecutor.
from invest-openapi-java-sdk.
@zlumyo а откуда ты получаешь onChangePortfolio
? У нас нет клиентских стримов, только общие по рынку
from invest-openapi-java-sdk.
Накидал псевдокод как работать с rest + stream в варианте работы с портфелем
class Strategy(api: OpenApi, stream: OpenApiStreaming) {
val portfolio = new AtomicReference[Portfolio]()
val orderbook = new ConcurrentHashMap[Figi, Prices]
val investumentInfo = new ConcurrentHashMap[Figi, Info]
val orders = new AtomicReference[Orders]
def initialize() = {
val portfolio = api.getPortfolio()
val balance = api.getBalance()
val orders = api.getOrders()
stream.subscribe("orderbook", portfolio.positions.figies) { event =>
orderbook.update(event.figi, event.prices)
onPrice(orderbook.get(figi), event)
}
stream.subscribe("instrument_info", portfolio.positions.figies) { event =>
investumentInfo.update(event.figi, event.info)
onInstrumentInfo(investumentInfo.get(figi), event)
}
}
def update() = {
val portfolio = api.getPortfolio()
val balance = api.getBalance()
val orders = api.getOrders()
}
def onPrice(old: Prices, new: Prices) = {
// Тут можно реагировать на цены инструментов в портфеле
}
def onInstrumentInfo(old: Info, new: Info) = {
// Тут можно реагировать на изменение статуса инструмента
}
def placeOrder() = {
// Тут можно обработать действия с портфелем
update() // А после обновить информацию
}
}
from invest-openapi-java-sdk.
По мониторингу рынка сегодня сделали тикет: https://github.com/TinkoffCreditSystems/invest-openapi/issues/41
Попробуем реализовать
from invest-openapi-java-sdk.
@NikitaMelnikov если мы хотим минимизировать количество запросов по Portfolio (при отсутствии стрима по нему), то придётся локально следить за изменениями в портфеле.
from invest-openapi-java-sdk.
а по Order было бы круто что-то типа того. Те отправка ордера и сразу по нему отлов событий результата.
new Order(Instrument, type, operation, q, price).Post(
onSuceesPost-> {}
onFailedPost-> {}
onComplited-> {}
onPartComplited-> {}
onDeleted-> {}
from invest-openapi-java-sdk.
И очень не хватает стрима по Orders и Portfolio для полной картины :)
Согласен, https://github.com/TinkoffCreditSystems/invest-openapi/issues/43
from invest-openapi-java-sdk.
Изначальная суть вопроса потеряла актуальность. Предложения по архитектуре представлены в других issues.
from invest-openapi-java-sdk.
Related Issues (20)
- Не приходит рублевой баланс портфеля HOT 2
- Ошибка при сборке Gradle-ом HOT 4
- Сделать возможным кастомизацию OkHttpClient'а, который используется OkHttpOpenApi HOT 2
- OpenAPI Java SDK версии 0.5 нет в репозитории Maven HOT 1
- Futures And ETFs HOT 1
- Брокерские счета HOT 1
- Не получается получить список исторических свечей HOT 5
- Объяснение механизма выставления статуса заявки HOT 7
- Приходят ошибочные цены свеч при подписке на StreamingEvent.Candle HOT 1
- Ошибка при получении суточных свечей ВТБ HOT 6
- Периодически возникает исключение 'Invalid character found in method name' HOT 1
- Как работать с LimitOrder HOT 8
- Websocket Подписка на все бумаги HOT 1
- Улучшение интервалов по свечам HOT 1
- В месячную свечу объем не вмещается в Integer! Можно сделать Long или BigDecimal. HOT 1
- StreamingContextImpl fails on restoring listener HOT 1
- https://tinkoffcreditsystems.github.io/invest-openapi/swagger-ui/swagger.yaml отдает ошибку 404 HOT 4
- /portfolio API doesn't allow to distinguish LONG and SHORT positions HOT 1
- При сборке ошибка Unable to read URL: https://tinkoffcreditsystems.github.io/invest-openapi/swagger-ui/swagger.yaml HOT 3
- Как проверить тип исторической операции, когда операция помечена как 'обрабатывается' HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from invest-openapi-java-sdk.