moex_iss 1.1.0 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2a3f9ad4ce42c5fe38d5b16bf09ec3d937654cf12225360c2c24f4a16b0322a
4
- data.tar.gz: fa3d5358f2ce99cf174c31a1eb27da86f2ba827d632bcd1214e19cd356080431
3
+ metadata.gz: dc6e59c116501d2490614026723ffe37b22c554da6a7e01283e61875b2ddd2aa
4
+ data.tar.gz: 2db4b513cb7cc9dcdd12ff144c5447b23d94ea4234dc6a856de899f2ae355ff4
5
5
  SHA512:
6
- metadata.gz: 5a9374940f414e6309bbb3fa1249c1406fb34932deeeb33d50a99c762faffede6a063dd891fa4fac96ec479da194c4dff5c8af5b7c81335cfe29243d40a268e9
7
- data.tar.gz: feee8548808c648d93726e2a79ac4240f15bd9afd4f469f7123cc743a714e8d12a56ea7d2147d4e42c9b9328fc492d07bb0ac0e048ca390ca3ac7cdb39984f47
6
+ metadata.gz: 71eb024e491423c345d14b08a25751cbc6a535a3766773aa8d3b70ff20a68085c8402a6b8bb9058f640d262dfc6a27cb6a4254a00a405cadf1bce5a82f8a9413
7
+ data.tar.gz: 8a0b310f3682a646ee0402e19b990b7ce64c5688df504a35720214321c1ab3b126bfb629f2d4192285f4d4b9d3459d7b7136274a88b214255e29de4f97987557
data/CHANGELOG.md CHANGED
@@ -4,4 +4,7 @@
4
4
  Формат основан на ведении журнала изменений, и этот проект придерживается семантического управления версиями.
5
5
  ## [1.1.0] - 2023-12-30
6
6
  ### Добавлено
7
- - Возможность работы с историческими данными акции
7
+ - Возможность работы с историческими данными акции
8
+ ## [1.11.0] - 2024-01-03
9
+ ### Добавлено
10
+ - Возможность получать данные об актуальных курсах валют ЦБ РФ
data/README.md CHANGED
@@ -22,7 +22,7 @@ gem "moex_iss"
22
22
 
23
23
  Или установите его самостоятельно как:
24
24
 
25
- $ gem install moex_api
25
+ $ gem install moex_iss
26
26
 
27
27
  ### Поддерживаемые Ruby версии
28
28
 
@@ -37,6 +37,18 @@ gem "moex_iss"
37
37
  client = MoexIss.client
38
38
  ```
39
39
 
40
+ ### Валюты
41
+ Для получения последних актульных данных о курсах валют:
42
+ ```ruby
43
+ currencies = client.currencies # => MoexIss::Market::Currencies
44
+
45
+ currencies.map(&:short_name) # -> ["USDRUB_TOM", "EURRUB_TOM", "CNYRUB_TOM"]
46
+
47
+ cny_rub = currencies.cny_rub # => MoexIss::Market::Currency
48
+ cny_rub.price = 12.5762
49
+ ...
50
+ ```
51
+
40
52
  ### Акции
41
53
 
42
54
  Для получения последних актульных данных:
@@ -65,9 +77,10 @@ stocks['2023-12-03'] # => MoexIss::Market::History::Stock
65
77
 
66
78
  Аргументы `from` и `till` можно использовать по одиночке
67
79
 
80
+ ### Обратите внимание
68
81
 
69
82
  Все экземпляры классов отвечает на метод `response`, который содержит полный ответ от MOEX ISS, из которого можно получать доп.параметры,
70
- так же у кажого класса свой набор спецефических методов для удобства работы с данными.
83
+ так же у каждого класса свой набор специфических методов для удобства работы с данными.
71
84
  ```ruby
72
85
  # Пример
73
86
  client.stock(:sber).market_price # => 271.37
@@ -6,15 +6,16 @@ module MoexIss
6
6
  include MoexIss::Hendler
7
7
 
8
8
  STOCKS_ENDPOINT = "engines/stock/markets/shares/boards/tqbr/securities"
9
+ CURRENCIES_ENDPOINT = "statistics/engines/currency/markets/selt/rates"
9
10
  STANDARD_PARAMS = {
10
11
  "iss.json" => "extended",
11
- "iss.only" => "securities,marketdata",
12
12
  "iss.meta" => "off"
13
13
  }
14
14
 
15
15
  def stocks
16
16
  endpoint = "#{STOCKS_ENDPOINT}.json"
17
17
  params = STANDARD_PARAMS
18
+ params["iss.only"] = "securities,marketdata"
18
19
 
19
20
  raw_response = get(endpoint, params)
20
21
 
@@ -26,12 +27,23 @@ module MoexIss
26
27
 
27
28
  endpoint = "#{STOCKS_ENDPOINT}/#{isin}.json"
28
29
  params = STANDARD_PARAMS
30
+ params["iss.only"] = "securities,marketdata"
29
31
 
30
32
  raw_response = get(endpoint, params)
31
33
 
32
34
  MoexIss::Market::Stock.new(handle_response(raw_response))
33
35
  end
34
36
 
37
+ def currencies
38
+ endpoint = "#{CURRENCIES_ENDPOINT}.json"
39
+ params = STANDARD_PARAMS
40
+ params["iss.only"] = "wap_rates"
41
+
42
+ raw_response = get(endpoint, params)
43
+
44
+ MoexIss::Market::Currencies.new(handle_response(raw_response))
45
+ end
46
+
35
47
  private
36
48
 
37
49
  def historical_data_of_the_stock(isin, from, till)
@@ -34,5 +34,3 @@ module MoexIss
34
34
  end
35
35
  end
36
36
  end
37
-
38
- # CURENCY https://iss.moex.com/iss/statistics/engines/currency/markets/selt/rates.json?iss.meta=off&iss.json=extended&iss.only=wap_rates
@@ -4,7 +4,8 @@ module MoexIss
4
4
  module Hendler
5
5
  def handle_response(response)
6
6
  return standard_hendler(response) if standard_schema?(response)
7
- return history_hendler(response) if history_schema?(response)
7
+ return response[1] if history_schema?(response)
8
+ return response[1] if currencies_schema?(response)
8
9
 
9
10
  fail MoexIss::Error::ResponseSchemaError, "Неизвестная схема ответа"
10
11
  end
@@ -22,14 +23,14 @@ module MoexIss
22
23
  response.is_a?(Array) && response[1]&.has_key?("history")
23
24
  end
24
25
 
26
+ def currencies_schema?(response)
27
+ response.is_a?(Array) && response[1]&.has_key?("wap_rates")
28
+ end
29
+
25
30
  def standard_hendler(response)
26
31
  response[1]["securities"].map.with_index do |x, i|
27
32
  {"securities" => x, "marketdata" => response[1]["marketdata"][i]}
28
33
  end
29
34
  end
30
-
31
- def history_hendler(response)
32
- response[1]
33
- end
34
35
  end
35
36
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexIss
4
+ module Market
5
+ class Collection
6
+ include Enumerable
7
+
8
+ attr_reader :response
9
+
10
+ def initialize(response, instance_class: Security)
11
+ @response = response
12
+ @instance_class = instance_class
13
+ @collection_map = {}
14
+
15
+ create_instances
16
+ end
17
+
18
+ def create_instances
19
+ @response.each do |data|
20
+ method = method_name(data)
21
+
22
+ setup_method(method, data)
23
+ end
24
+ end
25
+
26
+ def each
27
+ @collection_map.values.each { |stock| yield stock }
28
+ end
29
+
30
+ private
31
+
32
+ def method_name(data)
33
+ :some_name
34
+ end
35
+
36
+ def setup_method(method, data)
37
+ @collection_map[method] = @instance_class.new(data)
38
+
39
+ self.class.send(:define_method, method) { @collection_map[method] }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexIss
4
+ module Market
5
+ class Currencies < Collection
6
+ def initialize(response, instance_class: MoexIss::Market::Currency)
7
+ super
8
+ end
9
+
10
+ def create_instances
11
+ @response["wap_rates"].each do |data|
12
+ method = method_name(data)
13
+
14
+ setup_method(method, data)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def method_name(data)
21
+ data["shortname"]
22
+ .split("_")
23
+ .first.downcase
24
+ .insert(3, "_")
25
+ .to_sym
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexIss
4
+ module Market
5
+ class Currency < Security
6
+ METHODS = {
7
+ "tradedate" => :trade_date, "tradetime" => :trade_time,
8
+ "secid" => :secid, "shortname" => :short_name,
9
+ "price" => :price, "lasttoprevprice" => :last_top_rev_price,
10
+ "nominal" => :nominal, "decimals" => :decimals
11
+ }.freeze
12
+ end
13
+ end
14
+ end
@@ -3,31 +3,17 @@
3
3
  module MoexIss
4
4
  module Market
5
5
  module History
6
- class Stock
6
+ class Stock < Security
7
7
  METHODS = {
8
8
  "TRADEDATE" => :trade_date, "SHORTNAME" => :short_name, "SECID" => :secid, "VALUE" => :value,
9
9
  "OPEN" => :open, "LOW" => :low, "HIGH" => :high, "LEGALCLOSEPRICE" => :legal_close_price,
10
10
  "VOLUME" => :volume
11
11
  }.freeze
12
12
 
13
- attr_reader(:response, *METHODS.values)
14
-
15
13
  def initialize(response)
16
- @response = response
17
-
18
- setup_instance_varibales(@response["history"])
19
- end
20
-
21
- private
22
-
23
- def setup_instance_varibales(data)
24
- return if data.nil?
25
-
26
- data.each do |key, value|
27
- next unless METHODS.has_key?(key)
14
+ setup_methods(response["history"])
28
15
 
29
- instance_variable_set("@#{METHODS[key]}", value)
30
- end
16
+ super
31
17
  end
32
18
  end
33
19
  end
@@ -3,15 +3,19 @@
3
3
  module MoexIss
4
4
  module Market
5
5
  module History
6
- class Stocks < MoexIss::Market::Stocks
7
- def create_instances_stock
6
+ class Stocks < Collection
7
+ def initialize(response, instance_class: MoexIss::Market::History::Stock)
8
+ super
9
+ end
10
+
11
+ def create_instances
8
12
  @response["history"].each do |data|
9
- @stocks_map[data["TRADEDATE"]] = History::Stock.new({"history" => data})
13
+ @collection_map[data["TRADEDATE"]] = @instance_class.new({"history" => data})
10
14
  end
11
15
  end
12
16
 
13
17
  def [](key)
14
- @stocks_map[key]
18
+ @collection_map[key]
15
19
  end
16
20
  end
17
21
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexIss
4
+ module Market
5
+ class Security
6
+ attr_reader :response
7
+
8
+ def initialize(response)
9
+ @response = response
10
+
11
+ setup_methods(response)
12
+ end
13
+
14
+ private
15
+
16
+ def setup_methods(data)
17
+ return if data.nil?
18
+
19
+ data.each do |key, value|
20
+ next unless self.class::METHODS.has_key?(key)
21
+
22
+ define_singleton_method self.class::METHODS[key] do
23
+ value
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -2,40 +2,24 @@
2
2
 
3
3
  module MoexIss
4
4
  module Market
5
- class Stock
5
+ class Stock < Security
6
6
  METHODS = {
7
7
  "BID" => :bid, "MARKETPRICETODAY" => :market_price_today,
8
8
  "MARKETPRICE" => :market_price, "SECID" => :secid,
9
9
  "SHORTNAME" => :short_name, "LATNAME" => :lat_name,
10
10
  "BOARDID" => :board_id, "BOARDNAME" => :board_name,
11
11
  "ISIN" => :isin, "PREVPRICE" => :prev_price,
12
- "PREVDATE" => :prev_date
12
+ "PREVDATE" => :prev_date, "CLOSEPRICE" => :close_price,
13
+ "OPEN" => :open, "LOW" => :low, "HIGH" => :high,
14
+ "LAST" => :last, "VALUE" => :value, "SYSTIME" => :systime
13
15
  }.freeze
14
16
 
15
- MARKET_DATA = %w[CLOSEPRICE OPEN LOW HIGH LAST VALUE SYSTIME]
16
-
17
- attr_reader(:response, :market_data, *METHODS.values)
18
-
19
17
  def initialize(response)
20
18
  @response = response.is_a?(Array) ? response.first : response
21
19
 
22
- setup_instance_varibales(@response["securities"])
23
- setup_instance_varibales(@response["marketdata"])
24
- setup_instance_varibales(@response["history"])
25
-
26
- @market_data = @response["marketdata"]&.slice(*MARKET_DATA)
27
- end
28
-
29
- private
30
-
31
- def setup_instance_varibales(data)
32
- return if data.nil?
33
-
34
- data.each do |key, value|
35
- next unless METHODS.has_key?(key)
36
-
37
- instance_variable_set("@#{METHODS[key]}", value)
38
- end
20
+ setup_methods(@response["securities"])
21
+ setup_methods(@response["marketdata"])
22
+ setup_methods(@response["history"])
39
23
  end
40
24
  end
41
25
  end
@@ -2,36 +2,15 @@
2
2
 
3
3
  module MoexIss
4
4
  module Market
5
- class Stocks
6
- include Enumerable
7
-
8
- attr_reader :response
9
-
10
- def initialize(response)
11
- @response = response
12
- @stocks_map = {}
13
-
14
- create_instances_stock
15
- end
16
-
17
- def create_instances_stock
18
- @response.each do |data|
19
- method = data["securities"]["SECID"].downcase.to_sym
20
-
21
- setup_method(method, data)
22
- end
23
- end
24
-
25
- def each
26
- @stocks_map.values.each { |stock| yield stock }
5
+ class Stocks < Collection
6
+ def initialize(response, instance_class: MoexIss::Market::Stock)
7
+ super
27
8
  end
28
9
 
29
10
  private
30
11
 
31
- def setup_method(method, data)
32
- @stocks_map[method] = Stock.new(data)
33
-
34
- self.class.send(:define_method, method) { @stocks_map[method] }
12
+ def method_name(data)
13
+ data["securities"]["SECID"].downcase.to_sym
35
14
  end
36
15
  end
37
16
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MoexIss # :nodoc:
4
- VERSION = "1.1.0"
4
+ VERSION = "1.11.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moex_iss
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vyacheslav Konovalov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-30 00:00:00.000000000 Z
11
+ date: 2024-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -96,8 +96,12 @@ files:
96
96
  - lib/moex_iss/connection.rb
97
97
  - lib/moex_iss/error.rb
98
98
  - lib/moex_iss/hendler.rb
99
+ - lib/moex_iss/market/collection.rb
100
+ - lib/moex_iss/market/currencies.rb
101
+ - lib/moex_iss/market/currency.rb
99
102
  - lib/moex_iss/market/history/stock.rb
100
103
  - lib/moex_iss/market/history/stocks.rb
104
+ - lib/moex_iss/market/security.rb
101
105
  - lib/moex_iss/market/stock.rb
102
106
  - lib/moex_iss/market/stocks.rb
103
107
  - lib/moex_iss/request.rb
@@ -126,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
130
  - !ruby/object:Gem::Version
127
131
  version: '0'
128
132
  requirements: []
129
- rubygems_version: 3.5.3
133
+ rubygems_version: 3.1.6
130
134
  signing_key:
131
135
  specification_version: 4
132
136
  summary: Client for MOEX ISS API