Coder Social home page Coder Social logo

tim55667757 / tksbrokerapi Goto Github PK

View Code? Open in Web Editor NEW
24.0 4.0 9.0 42.76 MB

TKSBrokerAPI is the trading platform for automation and simplifying the implementation of trading scenarios, as well as working with Tinkoff Invest API server via the REST protocol. The TKSBrokerAPI platform may be used in two ways: from the console, it has a rich keys and commands, or you can use it as Python module.

Home Page: https://tim55667757.github.io/TKSBrokerAPI/

License: Apache License 2.0

Python 100.00%
tinkoff tinkoff-api api-client rest-api client stock trading cli history rest candlesticks prices statistics trade trading-api trading-platform python-api algo-trading-software algo-trading-strategies algotrading

tksbrokerapi's People

Contributors

tim55667757 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

Watchers

 avatar  avatar  avatar  avatar

tksbrokerapi's Issues

raise JSONDecodeError("Expecting value", s, err.value) from None

Add a clear notification when raise JSONDecodeError("Expecting value", s, err.value) from None trace when there is no connection.

Traceback (most recent call last):
  File "TKSBrokerAPI.py", line 2065, in <module>
    Main()
  File "TKSBrokerAPI.py", line 1895, in Main
    server = TinkoffBrokerServer(args.token, instrumentsList=instruments)  # Init class for trading with Tinkoff Broker
  File "TKSBrokerAPI.py", line 104, in __init__
    self.instrumentsList = instrumentsList if instrumentsList is not None else self.Listing()  # dictionary with stocks, currencies, bonds and etfs supports by broker. You can define this param whwn class init to reduce server requests.
  File "TKSBrokerAPI.py", line 275, in Listing
    instrumentsList = self._SendRequest(stocksURL, debug=showDebug)["payload"]["instruments"]
  File "TKSBrokerAPI.py", line 191, in _SendRequest
    responseJSON = self._ParseJSON(response.text, debug=False)
  File "TKSBrokerAPI.py", line 125, in _ParseJSON
    responseJSON = json.loads(rawData, encoding="UTF-8")
  File "c:\python3\lib\json\__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "c:\python3\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "c:\python3\lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Broken table when ETF requested

$ tksbrokerapi --prices IBM MSFT GOOGL UNKNOWN_TICKER POSI YNDX TGLD --output some-prices.md
TKSBrokerAPI.py     L:977  WARNING [2022-07-27 00:21:57,776] Instrument [UNKNOWN_TICKER] not in list of available instruments for current token!
TKSBrokerAPI.py     L:1018 INFO    [2022-07-27 00:21:58,048] Only unique instruments are shown:
# Actual prices at: [2022-07-26 21:21 UTC]

| Ticker       | FIGI         | Type       | Prev. close | Last price  | Chg. %   | Day limits min/max  | Actual sell / buy   | Curr.
|--------------|--------------|------------|-------------|-------------|----------|---------------------|---------------------|------
| IBM          | BBG000BLNNH6 | Shares     |      128.08 |      128.36 |   +0.22% |      126.7 / 130.02 |     127.67 / 128.65 | usd
| MSFT         | BBG000BPH459 | Shares     |      251.90 |      252.14 |   +0.10% |     248.74 / 254.96 |     252.01 / 252.14 | usd
| GOOGL        | BBG009S39JX6 | Shares     |      105.02 |      108.34 |   +3.16% |      97.24 / 118.76 |     108.36 / 108.37 | usd
| POSI         | TCS00A103X66 | Shares     |      910.00 |      910.00 |    0.00% |      533.2 / 1243.6 |           N/A / N/A | rub
| YNDX         | BBG006L8G4H1 | Shares     |     2136.00 |     2136.00 |    0.00% |     1672.6 / 2268.4 |           N/A / N/A | rub
| TGLD         | BBG222222222 | Etfs       |        0.07 |        0.07 |    0.00% | 0.06080000000000001 / 0.0815 |           N/A / N/A | usd

TKSBrokerAPI.py     L:1024 INFO    [2022-07-27 00:21:58,052] Price list for all instruments saved to file: x:\work\projects\PriceGenerator\some-prices.md

For `--history` key add possibility to view html chart with `PriceGenerator` package

Add key --render-chart with two possible parameter: interact (i) or non-interact (ni).

If you select interact then chain of candlesticks will render as interactive Bokeh chart. See examples: https://github.com/Tim55667757/PriceGenerator#overriding-parameters

If you select non-interact then chain of candlesticks will render as not interactive Google Candlestick chart. See examples:
https://github.com/Tim55667757/PriceGenerator#statistics-and-chart-on-a-simple-template

Simple CI/CD

  1. Some CI stages: unit-tests + build package (+ func. tests in future).
  2. CD: simple release cycle with dev builds in feature brunches and release builds in master brunch, and then publish into PyPI stage.

Add some overview keys

  • --overview-digest -- shows digest
  • --overview-positions -- shows only open positions
  • --overview-orders -- shows only orders section
  • --overview-analytics -- shows only analytics and distributions section

Implement the `RequestTradingStatus()` method using `SearchByTicker()` and `SearchByFIGI()`

For the --info key, add the display of the trading status for the instrument, and also implement the RequestTradingStatus() method using SearchByTicker() and SearchByFIGI(), also include "buyAvailableFlag" and "sellAvailableFlag" and "shortEnabledFlag".

There is a field "Current broker security trading status", but there are no other parameters: "limitOrderAvailableFlag", "marketOrderAvailableFlag" and "apiTradeAvailableFlag"

See: https://tinkoff.github.io/investAPI/swagger-ui/#/MarketDataService/MarketDataService_GetTradingStatus

Implement scenario: simple trailing stop

A trailing stop is a tool that allows you to automatically place an order (limit or SL/TP stop-order) at the required level from the current price, as a percentage or in the currency of the traded instrument. It is perfect to use when the market moves strongly in one direction, and the trader does not have the opportunity to follow the price change.

A trailing stop order is placed for the first time when the price crosses the breakeven level (open price, plus all commissions, plus a small floating step) and goes further than this level by the trailing amount. In the future, the trailing stop moves along with the price when it moves in a favorable direction and remains unchanged during reversals, which guarantees profit maximization. There is no need to manually place any SL/TP orders.

Trailing stop tracking directions can be "short" (for sell positions) and "long" (for buy positions). If the price has changed again and it is required to move the trailing stop order, then the previous one is canceled at the beginning and then a new order with a new level is placed.

In this task, you need to add a new script to the python api examples that implements a "simple" trailing stop. The user is allowed to specify:

  • fixed trailing level from the current price, in percentage or in the currency of the traded instrument;
  • a list of instrument tickers (except for currencies) for which you want to create a trailing stop;
    • either specify keywords (case insensitive): TS-ALL, TRAILING-STOP-ALL to create trailing stops for all instruments in the portfolio;
    • or specify the keywords (case insensitive): TS-[SHARES]-[BONDS]-[ETFS]-[FUTURES], TRAILING-STOP-[SHARES]-[BONDS]-[ETFS]-[FUTURES] to set trailing stops only for the specified types of instruments, you can several at once (for example, TS-SHARES-ETFS);
  • the type of orders placed for trailing stops: limit (valid until the end of the trading session) or stop orders (will be valid until canceled, until executed or until the trailing stop is automatically moved);
  • directions for all trailing stop orders: LONG, SHORT, or separately for each instrument.

Setting trailing stops for the list of specified instruments should be carried out in parallel mode using the multiprocessing library.


Описание задачи по-русски:

Трейлинг-стоп (или "скользящий" стоп) – это инструмент, который позволяет автоматически устанавливать ордер (лимитный или SL/TP стоп-ордер) на необходимом уровне от текущей цены, в процентах или в валюте торгуемого инструмента. Он отлично подойдет, когда рынок сильно движется в одном направлении, а у трейдера нет возможности следить за изменением цены.

Ордер для трейлинг-стопа выставляется в первый раз тогда, когда цена пересекает уровень безубыточности (цена открытия, плюс все комиссии, плюс небольшой плавающий шаг) и становится дальше этого уровня на величину трейлинга. В дальнейшем трейлинг-стоп перемещается вслед за ценой, когда она движется в благоприятном направлении и остаётся неизменным при разворотах, что гарантирует максимизацию прибыли. Устанавливать при этом вручную какие-либо SL/TP-ордера не требуется.

Направления для отслеживания трейлинг-стопа могут быть "short" (для позиций продаж) и "long" (для позиций покупок). Если цена в очередной раз изменилась и требуется передвинуть трейлинг-стоп ордер, то в начале отменяется предыдущий и затем выставляется новый ордер с новым уровнем.

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

  • фиксированный уровень трейлинга от текущей цены, в процентах или в валюте торгуемого инструмента;
  • список тикеров инструментов (кроме валют), по которым требуется создать трейлинг-стоп;
    • либо указать ключевые слова (регистронезависимо): TS-ALL, TRAILING-STOP-ALL для создания трейлинг-стопов для всех инструментов в портфеле;
    • либо указать ключевые слова (регистронезависимо): TS-[SHARES]-[BONDS]-[ETFS]-[FUTURES], TRAILING-STOP-[SHARES]-[BONDS]-[ETFS]-[FUTURES] для выставления трейлинг-стопов только по указанным типам инструментов, можно сразу по нескольким (например, TS-SHARES-ETFS);
  • тип выставляемых ордеров для трейлинг-стопов: лимитные (действуют до конца торговой сессии) или стоп-ордера (будут действовать до отмены, до исполнения или до автоматического перемещения трейлинг-стопа);
  • направления для всех трейлинг-стоп ордеров: LONG, SHORT, либо по каждому инструменту отдельно.

Установка трейлинг-стопов по списку указанных инструментов должна осуществляться в параллельном режиме с использованием библиотеки для мультипроцессинга.

Implement scenario: automatic trailing stop

See also: #50

A trailing stop is a tool that allows you to automatically place an order (limit or SL/TP stop-order) at the required level from the current price, as a percentage or in the currency of the traded instrument. It is perfect to use when the market moves strongly in one direction, and the trader does not have the opportunity to follow the price change. Unlike a "simple" trailing stop, the offset level from the current price for automatic trailing is determined by probabilistic-statistical methods.

A trailing stop order is placed for the first time when the price crosses the breakeven level (open price, plus all commissions, plus a small floating step) and goes further than this level by the trailing amount. In the future, the trailing stop moves along with the price when it moves in a favorable direction and remains unchanged during reversals, which guarantees profit maximization. There is no need to manually place any SL/TP orders.

Trailing stop tracking directions can be "short" (for sell positions) and "long" (for buy positions). If the price has changed again and it is required to move the trailing stop order, then the previous one is canceled at the beginning and then a new order with a new level is placed. The offset level for automatic trailing is calculated each time anew, by probabilistic-statistical methods, based on the previous N candles of a given timeframe.

In this task, you need to add a new script to the python api examples that implements an automatic trailing stop. The user is allowed to specify:

  • how to measure the trailing level from the current price: as a percentage or in the currency of the traded instrument (the offset will be determined automatically);
  • the number N of candles, on the basis of which it is necessary to perform a probabilistic-statistical analysis and determine a sufficient offset level at the current time;
  • a list of instrument tickers (except for currencies) for which you want to create a trailing stop;
    • either specify keywords (case insensitive): TS-ALL, TRAILING-STOP-ALL to create trailing stops for all instruments in the portfolio;
    • or specify the keywords (case insensitive): TS-[SHARES]-[BONDS]-[ETFS]-[FUTURES], TRAILING-STOP-[SHARES]-[BONDS]-[ETFS]-[FUTURES] to set trailing stops only for the specified types of instruments, you can several at once (for example, TS-SHARES-ETFS);
  • the type of orders placed for trailing stops: limit (valid until the end of the trading session) or stop orders (will be valid until canceled, until executed or until the trailing stop is automatically moved);
  • directions for all trailing stop orders: LONG, SHORT, or separately for each instrument.

Setting trailing stops for the list of specified instruments should be carried out in parallel mode using the multiprocessing library.


Описание задачи по-русски:

Смотрите также смежную задачу для реализации "простого" трейлинга: #50

Трейлинг-стоп (или "скользящий" стоп) – это инструмент, который позволяет автоматически устанавливать ордер (лимитный или SL/TP стоп-ордер) на необходимом уровне от текущей цены, в процентах или в валюте торгуемого инструмента. Он отлично подойдет, когда рынок сильно движется в одном направлении, а у трейдера нет возможности следить за изменением цены. В отличие от "простого" трейлинг-стопа, уровень отступа от текущей цены для автоматического трейлинга определяется вероятностно-статистическими методами.

Ордер для трейлинг-стопа выставляется в первый раз тогда, когда цена пересекает уровень безубыточности (цена открытия, плюс все комиссии, плюс небольшой плавающий шаг) и становится дальше этого уровня на величину трейлинга. В дальнейшем трейлинг-стоп перемещается вслед за ценой, когда она движется в благоприятном направлении и остаётся неизменным при разворотах, что гарантирует максимизацию прибыли. Устанавливать при этом вручную какие-либо SL/TP-ордера не требуется.

Направления для отслеживания трейлинг-стопа могут быть "short" (для позиций продаж) и "long" (для позиций покупок). Если цена в очередной раз изменилась и требуется передвинуть трейлинг-стоп ордер, то в начале отменяется предыдущий и затем выставляется новый ордер с новым уровнем. Уровень отступа для автоматического трейлинга вычисляется каждый раз заново, вероятностно-статистическими методами, на основании предыдущих N свечей заданного таймфейма.

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

  • в чём измерять уровень трейлинга от текущей цены: в процентах или в валюте торгуемого инструмента (сам отступ будет определяться автоматически);
  • количество N свечей, на основании которых необходимо выполнить вероятностно-статистический анализ и определить достаточный уровень отступа на текущий момент времени;
  • список тикеров инструментов (кроме валют), по которым требуется создать трейлинг-стоп;
    • либо указать ключевые слова (регистронезависимо): TS-ALL, TRAILING-STOP-ALL для создания трейлинг-стопов для всех инструментов в портфеле;
    • либо указать ключевые слова (регистронезависимо): TS-[SHARES]-[BONDS]-[ETFS]-[FUTURES], TRAILING-STOP-[SHARES]-[BONDS]-[ETFS]-[FUTURES] для выставления трейлинг-стопов только по указанным типам инструментов, можно сразу по нескольким (например, TS-SHARES-ETFS);
  • тип выставляемых ордеров для трейлинг-стопов: лимитные (действуют до конца торговой сессии) или стоп-ордера (будут действовать до отмены, до исполнения или до автоматического перемещения трейлинг-стопа);
  • направления для всех трейлинг-стоп ордеров: LONG, SHORT, либо по каждому инструменту отдельно.

Установка трейлинг-стопов по списку указанных инструментов должна осуществляться в параллельном режиме с использованием библиотеки для мультипроцессинга.

KeyError: 'asks' when no response from server with current prices

If server not responses with current prices. an error occured:

TKSBrokerAPI.py     L:797  DEBUG   [2022-07-22 17:07:45,401] Requesting current prices for instrument with ticker [POSI] and FIGI [TCS00A103X66]...
TKSBrokerAPI.py     L:357  DEBUG   [2022-07-22 17:07:55,483]     - not oK status code received: [504] {"code":4,"message":null,"description":null}
TKSBrokerAPI.py     L:361  DEBUG   [2022-07-22 17:07:55,484] Retry: [1]. Wait until 5 sec. and try again...
TKSBrokerAPI.py     L:367  ERROR   [2022-07-22 17:08:00,573] Not `oK` status received from broker server!
TKSBrokerAPI.py     L:368  ERROR   [2022-07-22 17:08:00,574]     - message: [504] {"code":4,"message":null,"description":null}
TKSBrokerAPI.py     L:797  DEBUG   [2022-07-22 17:08:00,574] Requesting current prices for instrument with ticker [POSI] and FIGI [TCS00A103X66]...
TKSBrokerAPI.py     L:357  DEBUG   [2022-07-22 17:08:10,663]     - not oK status code received: [504] {"code":4,"message":null,"description":null}
TKSBrokerAPI.py     L:361  DEBUG   [2022-07-22 17:08:10,664] Retry: [1]. Wait until 5 sec. and try again...
TKSBrokerAPI.py     L:357  DEBUG   [2022-07-22 17:08:25,755]     - not oK status code received: [504] {"code":4,"message":null,"description":null}
TKSBrokerAPI.py     L:361  DEBUG   [2022-07-22 17:08:25,756] Retry: [2]. Wait until 5 sec. and try again...
TKSBrokerAPI.py     L:357  DEBUG   [2022-07-22 17:08:40,842]     - not oK status code received: [504] {"code":4,"message":null,"description":null}
TKSBrokerAPI.py     L:361  DEBUG   [2022-07-22 17:08:40,842] Retry: [3]. Wait until 5 sec. and try again...
TKSBrokerAPI.py     L:357  DEBUG   [2022-07-22 17:08:55,933]     - not oK status code received: [504] {"code":4,"message":null,"description":null}
TKSBrokerAPI.py     L:367  ERROR   [2022-07-22 17:08:55,934] Not `oK` status received from broker server!
TKSBrokerAPI.py     L:368  ERROR   [2022-07-22 17:08:55,935]     - message: [504] {"code":4,"message":null,"description":null}
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,938] Traceback (most recent call last):
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,938]   File "tksbrokerapi\TKSBrokerAPI.py", line 2869, in Main
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,939]     server.Overview(showStatistics=True)
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,939]   File "tksbrokerapi\TKSBrokerAPI.py", line 1370, in Overview
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,939]     instrument = self.SearchByFIGI(requestPrice=True)  # full raw info about instrument by FIGI
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,940]   File "tksbrokerapi\TKSBrokerAPI.py", line 755, in SearchByFIGI
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,940]     figiJSON["currentPrice"] = self.GetCurrentPrices(showPrice=False)
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,941]   File "tksbrokerapi\TKSBrokerAPI.py", line 805, in GetCurrentPrices
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,941]     prices["buy"] = [{"price": NanoToFloat(item["price"]["units"], item["price"]["nano"]), "quantity": int(item["quantity"])} for item in pricesResponse["asks"]]
TKSBrokerAPI.py     L:3025 DEBUG   [2022-07-22 17:08:55,942] KeyError: 'asks'

Get rid of duplicate price requests

Improvements.

Get rid of duplicate price requests for the same instruments when requesting multiple prices for instruments in --prices

Get rid of duplicate price requests in the Overview() method when requesting prices for orders for the same instruments.

Some problems when trying to execute `--close-all orders`

Some problems when trying to --close-all orders:

TKSBrokerAPI.py     L:2665 DEBUG   [2022-07-21 11:17:39,117] Closing all available ['orders']. Currency positions you must closes manually using buy or sell operations! Wait, please...
TKSBrokerAPI.py     L:1063 DEBUG   [2022-07-21 11:17:39,118] Requesting current actual pending orders. Wait, please...
TKSBrokerAPI.py     L:1069 DEBUG   [2022-07-21 11:17:39,249] [0] records about pending orders successfully received
TKSBrokerAPI.py     L:1080 DEBUG   [2022-07-21 11:17:39,250] Requesting current actual stop orders. Wait, please...
TKSBrokerAPI.py     L:1086 DEBUG   [2022-07-21 11:17:39,389] [7] records about stop orders successfully received
TKSBrokerAPI.py     L:2638 INFO    [2022-07-21 11:17:39,389] Found: [0] opened pending and [7] stop orders. Let's trying to cancel it all. Wait, please...
TKSBrokerAPI.py     L:1063 DEBUG   [2022-07-21 11:17:39,390] Requesting current actual pending orders. Wait, please...
TKSBrokerAPI.py     L:1069 DEBUG   [2022-07-21 11:17:39,526] [0] records about pending orders successfully received
TKSBrokerAPI.py     L:2605 DEBUG   [2022-07-21 11:17:39,527] Cancelling stop order with ID: [2b60ac95-743f-4fa9-9ea0-f1e4af222a27]. Wait, please...
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,729] Traceback (most recent call last):
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,729]   File "X:\work\projects\TKSBrokerAPI\tksbrokerapi\TKSBrokerAPI.py", line 3016, in Main
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,730]     server.CloseAll(*args.close_all)
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,730]   File "X:\work\projects\TKSBrokerAPI\tksbrokerapi\TKSBrokerAPI.py", line 2669, in CloseAll
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,731]     self.CloseAllOrders()  # close all pending and stop orders
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,731]   File "X:\work\projects\TKSBrokerAPI\tksbrokerapi\TKSBrokerAPI.py", line 2640, in CloseAllOrders
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,732]     self.CloseOrders(allOrdersIDs + allStopOrdersIDs, allOrdersIDs, allStopOrdersIDs)
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,733]   File "X:\work\projects\TKSBrokerAPI\tksbrokerapi\TKSBrokerAPI.py", line 2615, in CloseOrders
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,733]     datetime.strptime(responseJSON["time"], "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=tzutc()).astimezone(tzlocal()).strftime("%Y-%m-%d %H:%M:%S"),
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,733]   File "C:\python3\lib\_strptime.py", line 577, in _strptime_datetime
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,734]     tt, fraction, gmtoff_fraction = _strptime(data_string, format)
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,734]   File "C:\python3\lib\_strptime.py", line 359, in _strptime
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,735]     (data_string, format))
TKSBrokerAPI.py     L:3027 DEBUG   [2022-07-21 11:17:39,735] ValueError: time data '2022-07-21T08:17:37.686748041Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'

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.