sqa 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a173b3b80876b7ae9279be648eb81a454224624a551dfeebfd3ff0f1b38ffa97
4
- data.tar.gz: daa28c0ee9d00cdc0cdb5e917f11e889458ef772918296f2195ab91255646c6a
3
+ metadata.gz: efdd7d63be5b0fd195ed3633a47759c701727e9dafdfd4f457ba6fec91f91426
4
+ data.tar.gz: e0acdaf0f99e81412313e6b1e5bc7de9d884e36e39f0be01c4942aa601e3c916
5
5
  SHA512:
6
- metadata.gz: 69af206b8b977846287cae8e00d1d7fa0cd31628605c6bb026a3654a1ff323f5653a69a761a5c1e1eae1f4424dde3c89d83f82f9f3bec14933a411b33ad292fe
7
- data.tar.gz: 419289d34fb9efda20fab1d65bdd4c0e1ad5835c80e7779fc3627253a777dd621ad325abcaf476ff2c53c51d2c3459b103f7f7f22fa9a199f4bbbf45f807946f
6
+ metadata.gz: 819b3afd73a08905b5d7047e16604be254821a68f48443740277be3cb2ad0950c59e311d7f41ec2e72a7c0feac698902fec8c3784fdb954a900c55b6dce52523
7
+ data.tar.gz: aeb60130dbfef691da2e561c40d5deacb61e90e0865502a74e3648be279797d3064a383b114f90c898f4327e5881fc7a40f70d70667ee40542a9eca5f5b25b0f
data/bin/sqa CHANGED
@@ -3,4 +3,4 @@
3
3
  require 'sqa'
4
4
  require 'sqa/cli'
5
5
 
6
- SQA::CLI.new.run
6
+ SQA.init
@@ -1 +1 @@
1
- f6678bb151447404c35d32d0dfe864bba5a4a0d4007b8f6f706d3de6e7415014881bca566320b80c62019f38cc1f3d2ca575c74c045a31bc23e2fb16ca87e0c2
1
+ b9ac08e43011c8c520b11d157e44e6b3a3ac73e6a81bd76ba6f6d6f0bbbdd113c1a9656f11470670406a3734dd3b337f8f82715c4160693284582c3dc8441a85
data/docs/data_frame.md CHANGED
@@ -13,6 +13,8 @@ There will be Daru extensions and patches made to adapt it to the specific needs
13
13
 
14
14
  Frankly, Ruby has lost the battle to Python w/r/t data analysis. The Python equivalent library to Daru is Pandas. It is actively maintained. There is a Ruby gem that uses PyCall to access Pandas but it is a few years out of date with open issues.
15
15
 
16
+ I am considering extracting the Daru::DataFrame class into a new gem `sqa-Ddata_frame` so that I can more easily make upgrades and refactor the old thing. It really could use a facelift and a better plugin strategy. The lib/daru/data_frame.rb is over 3,000 lines long. There is a lot of method documentation; but, I not really sure that all of those methods are really needed. We could at least extract each of the methods out into its own file.
17
+
16
18
  ## Creating a DataFrame from a CSV File
17
19
 
18
20
  A common activity is to use financial websites such as https://finance.yahoo.com to download historical price data for a stock.
@@ -21,6 +23,10 @@ Here is how to create a DataFrame from a CSV file downloaded from Finance.yahoo.
21
23
 
22
24
  ```ruby
23
25
  df = Daru::DataFrame.from_csv('aapl.csv')
26
+
27
+ # The SQA way uses the file's type to invoke the
28
+ # correct method.
29
+ df = SQA::DataFrame.load(filename)
24
30
  ```
25
31
 
26
32
  The Daru::DataFrame class can be created from many different sources including an ActiveRecord relation -- e.g. you can get you data from a database.
@@ -156,9 +162,3 @@ puts df.ai("Yes; but, should I buy this stock now?")
156
162
  ```
157
163
  Consulting the magic eight ball cluster.... The future looks cloudy. You should have bought it 14 days ago when I told you it was on its way up! Do you ever listen to me? No! I slave over these numbers night and day. I consult the best magic eight ball sources available. What do I get for my efforts? Nothing!
158
164
 
159
-
160
-
161
-
162
-
163
-
164
-
@@ -0,0 +1,47 @@
1
+ # libsvm File Format
2
+
3
+ This file format is used by rumale.
4
+
5
+ We're choosing the "Adj Close" column as the one that we want to predict.
6
+
7
+ The libsvm file format is simple. All values are numberic.
8
+
9
+ The first entry on a line is the thing that we want to predict. In this case it is the adjusted closing price. This is followed by a space.
10
+
11
+ What follows is a series of data pairs seperated by spaces in the form:
12
+
13
+ * index:value
14
+
15
+ where index is the column number and value is the value for that item.
16
+
17
+
18
+ ```ruby
19
+ require 'csv'
20
+
21
+ # Read CSV file
22
+ data = CSV.read('input.csv', headers: true)
23
+
24
+ # Open output file
25
+ output_file = File.open('output.txt', 'w')
26
+
27
+ # Convert data into libsvm format and write to output file
28
+ data.each do |row|
29
+ # Get the label (the "close" value)
30
+ label = row['Adj Close']
31
+
32
+ # Start building the libsvm formatted line
33
+ libsvm_line = "#{label} "
34
+
35
+ # Add feature indices and values
36
+ row.each_with_index do |(column, value), index|
37
+ next if column == 'Date' || column == 'Adj Close' # Skip irrelevant columns
38
+ libsvm_line += "#{index}:#{value} "
39
+ end
40
+
41
+ # Write the libsvm formatted line to the output file
42
+ output_file.puts(libsvm_line)
43
+ end
44
+
45
+ # Close files
46
+ output_file.close
47
+ ```
data/lib/sqa/cli.rb CHANGED
@@ -4,21 +4,35 @@ require_relative '../sqa'
4
4
 
5
5
  module SQA
6
6
  class CLI
7
- def initialize
8
- @args = $ARGV.dup
9
- end
10
-
11
- def run
12
- stock = Stock.new('aapl')
13
-
14
- puts <<~OUTPUT
15
-
16
- TBD
17
- @args => #{@args}
18
- stock => #{stock}
19
-
20
- OUTPUT
21
- end
7
+ include Mixlib::CLI
8
+
9
+ option :config_file,
10
+ short: "-c CONFIG",
11
+ long: "--config CONFIG",
12
+ default: "~/.sqa.rb",
13
+ description: "The configuration file to use"
14
+
15
+ option :log_level,
16
+ short: "-l LEVEL",
17
+ long: "--log_level LEVEL",
18
+ description: "Set the log level (debug, info, warn, error, fatal)",
19
+ required: true,
20
+ in: [:debug, :info, :warn, :error, :fatal],
21
+ proc: Proc.new { |l| l.to_sym }
22
+
23
+ option :help,
24
+ short: "-h",
25
+ long: "--help",
26
+ description: "Show this message",
27
+ on: :tail,
28
+ boolean: true,
29
+ show_options: true,
30
+ exit: 0
31
+
32
+ def run(argv = ARGV)
33
+ parse_options(argv)
34
+ SQA::Config.merge!(config)
35
+ end
22
36
  end
23
37
  end
24
38
 
@@ -3,9 +3,13 @@
3
3
 
4
4
  class SQA::DataFrame < Daru::DataFrame
5
5
  class YahooFinance
6
- def self.from_csv(ticker)
7
- df = SQA::DataFrame.from_csv(ticker)
6
+ def self.load(filename, options={}, &block)
7
+ df = SQA::DataFrame.load(filename, options={}, &block)
8
8
 
9
+ # ASSUMPTION: This is the column headers from Yahoo Finance for
10
+ # CSV files. If the file type is something different from the
11
+ # same source, they may not be the same.
12
+ #
9
13
  new_names = {
10
14
  "Date" => :timestamp,
11
15
  "Open" => :open_price,
@@ -8,22 +8,20 @@ class SQA::DataFrame < Daru::DataFrame
8
8
  SQA::Config.data_dir + filename
9
9
  end
10
10
 
11
- def self.from_csv(ticker)
12
- df = super(path("#{ticker.downcase}.csv"))
13
- df[:ticker] = ticker
14
- df
15
- end
16
-
17
- def self.load(filename)
11
+ def self.load(filename, options={}, &block)
18
12
  source = path(filename)
19
13
  type = source.extname.downcase
20
14
 
21
15
  if ".csv" == type
22
- @df = Daru::DataFrame.from_csv(source)
16
+ from_csv(source, options={}, &block)
23
17
  elsif ".json" == type
24
- @df = Daru::DataFrame.from_json(source)
18
+ from_json(source, options={}, &block)
19
+ elsif %w[.txt .dat].include?(type)
20
+ from_plaintext(source, options={}, &block)
21
+ elsif ".xls" == type
22
+ from_excel(source, options={}, &block)
25
23
  else
26
- raise SQA::BadParamenterError, "supports csv or json only"
24
+ raise SQA::BadParamenterError, "un-suppod file type: #{type}"
27
25
  end
28
26
  end
29
27
  end
data/lib/sqa/portfolio.rb CHANGED
@@ -3,7 +3,9 @@
3
3
  class SQA::Portfolio
4
4
  attr_accessor :df
5
5
 
6
- def initialize(filename="portfolio.csv")
6
+ def initialize(
7
+ filename = SQA::Config.portfolio_filename
8
+ )
7
9
  @df = SQA::DataFrame.load(filename)
8
10
  end
9
11
  end
data/lib/sqa/stock.rb CHANGED
@@ -6,10 +6,12 @@ class SQA::Stock
6
6
  attr_accessor :ticker
7
7
 
8
8
  def initialize(ticker:, source: :yahoo_finance, type: :csv)
9
- @ticker = ticker
9
+ @ticker = ticker.downcase
10
10
  @company_name = "Company Name"
11
11
  klass = "SQA::DataFrame::#{source.to_s.camelize}".constantize
12
- @df = klass.send("from_#{type.downcase}", ticker)
12
+ filename = "#{@ticker}.#{type}"
13
+ @df = klass.send(:load, filename)
14
+ @df[:ticker] = ticker
13
15
  end
14
16
 
15
17
  def to_s
data/lib/sqa/trade.rb CHANGED
@@ -4,7 +4,9 @@
4
4
  class SQA::Trade
5
5
  attr_accessor :df
6
6
 
7
- def initialize(filename="trades.csv")
7
+ def initialize(
8
+ filename = SQA::Config.trades_filename
9
+ )
8
10
  @df = SQA::DataFrame.load(filename)
9
11
  end
10
12
 
data/lib/sqa/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SQA
4
4
  module Version
5
- VERSION = "0.0.6"
5
+ VERSION = "0.0.7"
6
6
  end
7
7
  end
data/lib/sqa.rb CHANGED
@@ -5,6 +5,7 @@ require 'active_support/core_ext/string'
5
5
  require 'daru'
6
6
  require 'date'
7
7
  require 'descriptive_statistics'
8
+ require 'mixlib/cli'
8
9
  require 'mixlib/config'
9
10
  require 'nenv'
10
11
  require 'pathname'
@@ -36,19 +37,39 @@ module SQA
36
37
  extend Mixlib::Config
37
38
  config_strict_mode true
38
39
 
39
- default :data_dir, HOME + "sqa_data"
40
- default :plotting_library, :gruff
41
- default :lazy_update, false
40
+ default :data_dir, HOME + "sqa_data"
41
+ default :plotting_library, :gruff # TODO: use svg-graph
42
+ default :lazy_update, false
43
+ default :portfolio_filename, "portfolio.csv"
44
+ default :trades_filename, "trades.csv"
45
+
46
+ default :log_level, :info
47
+ default :config_file, "~/.sqa.rb"
48
+
42
49
  end
43
50
 
44
51
  def self.init
52
+ SQA::CLI.new.run if defined? SQA::CLI
53
+
54
+ Config.config_file = Pathname.new homify(Config.config_file)
55
+
56
+ Config.from_file(Config.config_file)
57
+
58
+ Config.data_dir = Pathname.new homify(Config.data_dir)
59
+
45
60
  Daru.lazy_update = Config.lazy_update
46
61
  Daru.plotting_library = Config.plotting_library
47
62
 
48
63
  nil
49
64
  end
65
+
66
+ def self.homify(filepath)
67
+ filepath.gsub(/^~/, Nenv.home)
68
+ end
50
69
  end
51
70
 
71
+ # require_relative "patches/daru" # TODO: extract Daru::DataFrame in new gem sqa-data_frame
72
+
52
73
  require_relative "sqa/data_frame"
53
74
  require_relative "sqa/errors"
54
75
  require_relative "sqa/indicator"
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.6
4
+ version: 0.0.7
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-08-18 00:00:00.000000000 Z
11
+ date: 2023-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: gruff
56
+ name: mixlib-cli
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -210,6 +210,7 @@ files:
210
210
  - docs/fibonacci_retracement.md
211
211
  - docs/head_and_shoulders_pattern.md
212
212
  - docs/identify_wave_condition.md
213
+ - docs/libsvm_file_format.md
213
214
  - docs/market_profile.md
214
215
  - docs/mean_reversion.md
215
216
  - docs/momentum.md