sqa 0.0.9 → 0.0.10
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 +4 -4
- data/README.md +6 -0
- data/checksums/sqa-0.0.10.gem.sha512 +1 -0
- data/lib/sqa/data_frame/yahoo_finance.rb +91 -14
- data/lib/sqa/data_frame.rb +30 -0
- data/lib/sqa/stock.rb +18 -4
- data/lib/sqa/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b699ff032eee80858f9cfc3c3cba7e1ad5c0b537cd9b014085d184f4ce052451
|
4
|
+
data.tar.gz: 3c7211690c31b6486718306d7e62fdf71c9466a421cfc694955a64e0d0184e66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8a319f9b59ce9af8cccf6ee0cd436e7847db90e95703da13ea50cf33d03cd5c5aeb996b87503f2ddc6f7991f18441be7c49a099377a19a89b6c8bd7ceb4eb3b
|
7
|
+
data.tar.gz: 9b7e5b5a16f21d256c44f8a491b6f4bc0b60cc507d9124b49b12d6da9c2e487f64b0f2388ecdc4e0d24e10eb4b4f2fd69f5ca190eb5a4f51af9aba7a1123d6ea
|
data/README.md
CHANGED
@@ -8,6 +8,12 @@ The BUY/SELL signals that it generates are part of a game. **DO NOT USE** when
|
|
8
8
|
|
9
9
|
I'm making use of lots of gems which may not be part of the gemspec at this time. I will be adding them as they make the final cut as to fitness for the intended function. Some gems are configurable. For example the default for the plotting library is `gruff`. There are several available that the `daru` gem can use.
|
10
10
|
|
11
|
+
### DARU or RedAmber
|
12
|
+
|
13
|
+
I'm just really using `daru` for its data frame object; However, I just learned about the RedAmber data frame object in Ruby based off of Apache Arrow. I'm going to look at that product since it is actively maintained.
|
14
|
+
|
15
|
+
https://github.com/red-data-tools/red_amber
|
16
|
+
|
11
17
|
## Installation
|
12
18
|
|
13
19
|
Install the gem and add to the application's Gemfile by executing:
|
@@ -0,0 +1 @@
|
|
1
|
+
2df18c06074d6725d838fcda7a72d5053859cc677898f799215a223720eadfc6eb393ab765b074926040b7509b6bb8e0a0b13e1181b0d1713951445a87ac7a6e
|
@@ -1,28 +1,105 @@
|
|
1
1
|
# lib/sqa/data_frame/yahoo_finance.rb
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require 'faraday'
|
5
|
+
require 'nokogiri'
|
6
|
+
|
4
7
|
class SQA::DataFrame < Daru::DataFrame
|
5
8
|
class YahooFinance
|
6
|
-
|
7
|
-
|
9
|
+
CONNECTION = Faraday.new(url: 'https://finance.yahoo.com')
|
10
|
+
HEADERS = %i[
|
11
|
+
timestamp # 0
|
12
|
+
open_price # 1
|
13
|
+
high_price # 2
|
14
|
+
low_price # 3
|
15
|
+
close_price # 4
|
16
|
+
adj_close_price # 5
|
17
|
+
volume # 6
|
18
|
+
]
|
8
19
|
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
20
|
+
# The Yahoo Finance Headers are being remapped so that
|
21
|
+
# the header can be used as a method name to access the
|
22
|
+
# vector.
|
12
23
|
#
|
13
|
-
|
14
|
-
"Date" =>
|
15
|
-
"Open" =>
|
16
|
-
"High" =>
|
17
|
-
"Low" =>
|
18
|
-
"Close" =>
|
19
|
-
"Adj Close" =>
|
20
|
-
"Volume" =>
|
24
|
+
HEADER_MAPPING = {
|
25
|
+
"Date" => HEADERS[0],
|
26
|
+
"Open" => HEADERS[1],
|
27
|
+
"High" => HEADERS[2],
|
28
|
+
"Low" => HEADERS[3],
|
29
|
+
"Close" => HEADERS[4],
|
30
|
+
"Adj Close" => HEADERS[5],
|
31
|
+
"Volume" => HEADERS[6]
|
21
32
|
}
|
22
33
|
|
23
|
-
|
34
|
+
################################################################
|
35
|
+
def self.load(filename, options={}, &block)
|
36
|
+
df = SQA::DataFrame.load(filename, options={}, &block)
|
37
|
+
|
38
|
+
headers = df.vectors
|
39
|
+
|
40
|
+
if headers.first == HEADERS.first.to_s
|
41
|
+
a_hash = {}
|
42
|
+
HEADERS.each {|k| a_hash[k.to_s] = k}
|
43
|
+
df.rename_vectors(a_hash)
|
44
|
+
else
|
45
|
+
df.rename_vectors(HEADER_MAPPING)
|
46
|
+
end
|
24
47
|
|
25
48
|
df
|
26
49
|
end
|
50
|
+
|
51
|
+
|
52
|
+
# Scrape the Yahoo Finance website to get recent
|
53
|
+
# historical prices for a specific ticker
|
54
|
+
#
|
55
|
+
# ticker String the security to retrieve
|
56
|
+
# returns a DataFrame
|
57
|
+
#
|
58
|
+
def self.recent(ticker)
|
59
|
+
response = CONNECTION.get("/quote/#{ticker.upcase}/history")
|
60
|
+
doc = Nokogiri::HTML(response.body)
|
61
|
+
table = doc.css('table').first
|
62
|
+
rows = table.css('tbody tr')
|
63
|
+
|
64
|
+
data = []
|
65
|
+
|
66
|
+
rows.each do |row|
|
67
|
+
cols = row.css('td').map{|c| c&.text}
|
68
|
+
next if cols[1]&.include?("Dividend")
|
69
|
+
cols[0] = Date.parse(cols[0]).to_s
|
70
|
+
cols[6] = cols[6].tr(',','').to_i
|
71
|
+
(1..5).each {|x| cols[x] = cols[x].to_f}
|
72
|
+
data << HEADERS.zip(cols).to_h
|
73
|
+
end
|
74
|
+
|
75
|
+
Daru::DataFrame.new(data)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Append update_df rows to the base_df
|
80
|
+
#
|
81
|
+
# base_df is ascending on timestamp
|
82
|
+
# update_df is descending on timestamp
|
83
|
+
#
|
84
|
+
# base_df content came from CSV file downloaded
|
85
|
+
# from Yahoo Finance.
|
86
|
+
#
|
87
|
+
# update_df came from scraping the webpage
|
88
|
+
# at Yahoo Finance for the recent history.
|
89
|
+
#
|
90
|
+
# Returns a combined DataFrame.
|
91
|
+
#
|
92
|
+
def self.append(base_df, updates_df)
|
93
|
+
last_timestamp = Date.parse base_df.timestamp.last
|
94
|
+
filtered_df = updates_df.filter_rows { |row| Date.parse(row[:timestamp]) > last_timestamp }
|
95
|
+
|
96
|
+
last_inx = filtered_df.size - 1
|
97
|
+
|
98
|
+
(0..last_inx).each do |x|
|
99
|
+
base_df.add_row filtered_df.row[last_inx-x]
|
100
|
+
end
|
101
|
+
|
102
|
+
base_df
|
103
|
+
end
|
27
104
|
end
|
28
105
|
end
|
data/lib/sqa/data_frame.rb
CHANGED
@@ -3,7 +3,37 @@
|
|
3
3
|
|
4
4
|
require_relative 'data_frame/yahoo_finance'
|
5
5
|
|
6
|
+
class Daru::DataFrame
|
7
|
+
|
8
|
+
def to_csv(path_to_file, opts={})
|
9
|
+
options = {
|
10
|
+
converters: :numeric
|
11
|
+
}.merge(opts)
|
12
|
+
|
13
|
+
writer = ::CSV.open(path_to_file, 'wb')
|
14
|
+
|
15
|
+
writer << vectors.to_a unless options[:headers] == false
|
16
|
+
|
17
|
+
each_row do |row|
|
18
|
+
writer << if options[:convert_comma]
|
19
|
+
row.map { |v| v.to_s.tr('.', ',') }
|
20
|
+
else
|
21
|
+
row.to_a
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
writer.close
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
6
32
|
class SQA::DataFrame < Daru::DataFrame
|
33
|
+
|
34
|
+
|
35
|
+
#################################################
|
36
|
+
|
7
37
|
def self.path(filename)
|
8
38
|
Pathname.new SQA.config.data_dir + filename
|
9
39
|
end
|
data/lib/sqa/stock.rb
CHANGED
@@ -8,10 +8,24 @@ class SQA::Stock
|
|
8
8
|
def initialize(ticker:, source: :yahoo_finance, type: :csv)
|
9
9
|
@ticker = ticker.downcase
|
10
10
|
@company_name = "Company Name"
|
11
|
-
klass
|
12
|
-
|
13
|
-
@
|
14
|
-
|
11
|
+
@klass = "SQA::DataFrame::#{source.to_s.camelize}".constantize
|
12
|
+
@type = type
|
13
|
+
@filename = "#{@ticker}.#{type}"
|
14
|
+
|
15
|
+
update_the_dataframe
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def update_the_dataframe
|
20
|
+
df1 = @klass.load(@filename)
|
21
|
+
df2 = @klass.recent(@ticker)
|
22
|
+
@df = @klass.append(df1, df2)
|
23
|
+
|
24
|
+
unless @df.size == df1.size
|
25
|
+
@df.send("to_#{@type}", SQA::DataFrame.path(@filename))
|
26
|
+
end
|
27
|
+
|
28
|
+
@df[:ticker] = @ticker
|
15
29
|
end
|
16
30
|
|
17
31
|
def to_s
|
data/lib/sqa/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sqa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dewayne VanHoozer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -278,6 +278,7 @@ files:
|
|
278
278
|
- Rakefile
|
279
279
|
- bin/sqa
|
280
280
|
- checksums/sqa-0.0.1.gem.sha512
|
281
|
+
- checksums/sqa-0.0.10.gem.sha512
|
281
282
|
- checksums/sqa-0.0.2.gem.sha512
|
282
283
|
- checksums/sqa-0.0.3.gem.sha512
|
283
284
|
- checksums/sqa-0.0.4.gem.sha512
|