sqa 0.0.3 → 0.0.5

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: 48ca0637f3792531412ee5d07c2fd49a28f167a04f797d535a5d81e8b47907fb
4
- data.tar.gz: e03b6c57017dab18c86a7e162ee4f9ff8c19567df92b29b0f132349959f802a9
3
+ metadata.gz: 54f8ba7f993ae95bf01b2cdeeb32c76b17b02df6799dc046b85fde9b3d54f202
4
+ data.tar.gz: 91ea7ae14f99322618c3854f7ac16c4ee79c9a7d39609228d589528c381644df
5
5
  SHA512:
6
- metadata.gz: 5d373732f21ea218e6b2614cd8ef45d93e23e59dbfada17bded86974559c0ca4a99426bcf131ddbd5a6286edbd27e7212f1fbe9c8c3ceaa6eeca1ef9b4888451
7
- data.tar.gz: b1c2b23bc8abd33c20c1337481c6f8e51243fe946fd6738f4cdea4f3f0c746233730f4b3cfc13710fc0f9e11dce0b248d22acfb08b21a7200599edc3a7b12a4f
6
+ metadata.gz: 7f20d2ed8800c892905e1155006794832af992c7f1309121860e62cc010b26d23af4d04f6e0b03775b4db0a8dbcafca321ea4c0a39ffc7f6533d6f75bbb59976
7
+ data.tar.gz: 014345e1802899212fb443bec50783988b535d143f7f8fae50ebbacf4a0a9bf52144d6417b395f342fa0f68d94aceb7878179e9eac2bf429f980af9689dd9249
data/README.md CHANGED
@@ -4,23 +4,109 @@ This is a very simplistic set of tools for running technical analysis on a stock
4
4
 
5
5
  The BUY/SELL signals that it generates are part of a game. **DO NOT USE** when real money is at stake.
6
6
 
7
+ ## This is a Work in Progress
8
+
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
+
7
11
  ## Installation
8
12
 
9
13
  Install the gem and add to the application's Gemfile by executing:
10
14
 
11
- $ bundle add sqa
15
+ bundle add sqa
12
16
 
13
17
  If bundler is not being used to manage dependencies, install the gem by executing:
14
18
 
15
- $ gem install sqa
19
+ gem install sqa
20
+
21
+ ## ShoutOut To `daru`
22
+
23
+ **D**ata **A**nalysis in **RU**by
24
+
25
+ http://github.com/v0dro/daru
26
+
27
+ Its `DataFrame` class is a very interesting in memory data structure.
16
28
 
17
29
  ## Usage
18
30
 
19
- Do not use!
31
+ **Do not use!**
32
+
33
+ ## Playing in IRB
34
+
35
+ You can play around in IRB with the SQA framework in two different areas. First is the stocks and indicators. The second is with trading strategies.
36
+
37
+ ### With Stocks and Indicators
38
+
39
+ You will need some CSV files.
40
+
41
+ #### Get Historical Prices
42
+
43
+ Go to https::/finance.yahoo.com and down some historical price data for your favorite stocks. Put those CSV files in to the `sqa_data` directory in your HOME directory.
44
+
45
+ You may need to create a `portfolio.csv` file or you may not. TODO
46
+
47
+ The CSV files will be named by the stock's ticker symbol. For example: AAPL.csv
48
+
49
+ ```ruby
50
+ require 'sqa'
51
+ # TODO: See the documentation on configurable items
52
+ # Omit to use defaults
53
+ SQA::Config.from_file(path_to_config_file)
54
+
55
+ # initialize framework from configuration values
56
+ SQA.init
57
+
58
+ aapl = SQA::Stock.new('aapl')
59
+ ```
60
+
61
+ `aapl.df` is the Daru::DataFrame
62
+ see the `daru` gem for how to manipulate the DataFrame
63
+ The SQA::Indicator class methods use Arrays not the DataFrame
64
+ Here is an example:
65
+
66
+
67
+ ```ruby
68
+ prices = aapl.df.adj_close_price.to_a
69
+ period = 14 # size of the window in prices to analyze
70
+
71
+ rsi = SQA::Indicator.rsi(prices, period)
72
+ ```
73
+
74
+ ### With Strategies
75
+
76
+ The strategies work off of an Object that contains the information required to make its recommendation. Build on the previous Ruby snippet ...
77
+
78
+ ```ruby
79
+ require 'ostruct'
80
+ vector = OpenStruct.new
81
+ vector.rsi = rsi
82
+
83
+ # Load some trading strategies
84
+ ss = SWA::Strategy.new
85
+ ss.auto_load # loads everything in the lib/sqa/strategy folder
86
+
87
+ # Select some strategies to execute
88
+ ss.add SWA::Strategy::Random # 3-sided coin flip
89
+ ss.add SQA::Strategy::RSI
90
+
91
+ # This is an Array with each "trade" method
92
+ # that is defined in each strategy added
93
+ ss.strategies
94
+
95
+ # Execute those strategies
96
+ results = ss.execute(vector)
97
+ ```
98
+
99
+ `results` is an Array with an entry for each strategy executed. The entries are either :buy, :sell or :hold.
100
+
101
+ Currently the strategies are executed sequentially so the results can easily be mapped back to which strategy produced which result. In the future that will change so that the strategies are executed concurrently. When that change is introduced the entries in the `results` object will change -- most likely to an Array of Hashes.
102
+
103
+ ### See my **experiments** Repository in the **stocks** Directory
104
+
105
+ I have a program `analysis.rb` that I'm writing along with this `sqa` gem. Its intended as a practical example/test case for how the gem can be used to analyze a complete portfolio one stock at a time.
20
106
 
21
107
  ## Contributing
22
108
 
23
- I can always use some help on this stuff. Got an idea for a new metric or analysis? Want to improve the math? Make the signals better? Let's collaborate!
109
+ I can always use some help on this stuff. Got an idea for a new indicator or strategy? Want to improve the math? Make the signals better? Let's collaborate!
24
110
 
25
111
  Bug reports and pull requests are welcome on GitHub at https://github.com/MadBomber/sqa.
26
112
 
@@ -0,0 +1 @@
1
+ 0bf41b69d8f760412a87aa119292b29f8d23c1a09daf059643314cb00fc251a5bd88a4843d9ed9e2493a9b177389a4bba2b7aff998d90bc7b50b81fb9fd81e47
@@ -0,0 +1 @@
1
+ e63dcb48ad13d1d8397b5445e25d15e58ede7191e6b9f5c5a106d701a01020036eb37cc1b45954d7fb7aa819527452df7b16b82678f439b138833c8ad0377dec
@@ -0,0 +1 @@
1
+ a307251c474edb1367cd0d0a7d2cc663acf98052d070273ff157a155370f87cb43fe10c33403fa53e7b07c9a649d00ef12013c7194fd19ee73c1955e0146b046
@@ -13,4 +13,17 @@ class SQA::DataFrame < Daru::DataFrame
13
13
  df[:ticker] = ticker
14
14
  df
15
15
  end
16
+
17
+ def self.load(filename)
18
+ source = path(filename)
19
+ type = source.extname.downcase
20
+
21
+ if ".csv" == type
22
+ @df = Daru::DataFrame.from_csv(source)
23
+ elsif ".json" == type
24
+ @df = Daru::DataFrame.from_json(source)
25
+ else
26
+ raise SQA::BadParamenterError, "supports csv or json only"
27
+ end
28
+ end
16
29
  end
data/lib/sqa/errors.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # lib/sqa/errors.rb
2
2
 
3
3
  module SQA
4
+ # raised when an API contract is broken
4
5
  class BadParameterError < ArgumentError; end
5
6
  end
@@ -0,0 +1,9 @@
1
+ # lib/sqa/portfolio.rb
2
+
3
+ class SQA::Portfolio
4
+ attr_accessor :df
5
+
6
+ def initialize(filename="portfolio.csv")
7
+ @df = SQA::DataFrame.load(filename)
8
+ end
9
+ end
@@ -0,0 +1,54 @@
1
+ # Trading Strategies
2
+
3
+ A **strategy** is implemented as a class within the namespace of SQA::Strategy -- see the file lib/sqa/strategy/random.rb as an example. All strategy classes should have a class method **trade** which is the primary entry point into the strategy. The class can be extended using the SQA::Strategy::Common module which adds common class methods such as **trade_against** and **desc**
4
+
5
+ ## The **trade** Class Method
6
+
7
+ The method accepts a single parameter called a vector. The vector parameter is an object that contains the information required by the strategy in order to make a recommendation. In the examples provided this object is an OpenStruct. You can either follow this pattern or use your own; however, at this time only one parameter is allowed for the trade method.
8
+
9
+ ## The **trade_against** Class Method
10
+
11
+ If **trade** is consistently wrong many more times than it is right, don't throw it out. Just start using the **trade_against** class method instead. This method takes the recommendation of the **trade** class method and suggests the opposite.
12
+
13
+ ## The **desc** Class Method
14
+
15
+ You can document your strategy in a markdown formatted file. The **desc** class method will look for the filename in the same directory as the strategy file. This is typically in the lib/sqa/strategy directory.
16
+
17
+ The **desc** class method will find the markdown file and return its contents as a String so that you can do with it as you please.
18
+
19
+ ## Example Strategies
20
+
21
+ The follow examples are provided:
22
+
23
+ * ema.rb
24
+ * mp.rb
25
+ * mr.rb
26
+ * random.rb
27
+ * rsi.rb
28
+ * sma.rb
29
+
30
+ ## Usage
31
+
32
+ Tge SQA::Strategy class manages an Array of trading strategies. You can add to the Array multiple strategies like this:
33
+
34
+ ```ruby
35
+ require 'sqa'
36
+ ss = SQA::Strategy.new
37
+ ss.add SQA::Strategy::Random.method(:trade)
38
+ ss.add SQA::Strategy::SMA.method(:trade)
39
+ ss.add SQA::Strategy::EMA
40
+ ```
41
+
42
+ Note that if your primary entry point to the trading strategy class is **trade** then the parameter to the **add** function does not have to include the ".method(:entry_point)" -- just use the class name by itself. If you do not use **trade** as as class method in you strategy class, then the **trade_against** method added by the SQA::Strategy::Common module will not work.
43
+
44
+ If you want to evaluate the **trade_against** class method in a strategy then you must the "ss.add SQA::Strategy::Random.method(:trade_against)" pattern.
45
+
46
+ Then for any specific stock create your vector object that contains all the information that the trading strategies need in order to make their recommendations. Once you have you vector you can then **execute** the Array of strategies.
47
+
48
+ ```ruby
49
+ vector = ...
50
+ result = ss.execute(vector)
51
+ ```
52
+
53
+ **result** will be an Array of recommendations from the different strategies on whether to :bur, :sell or :hold.
54
+
@@ -0,0 +1,38 @@
1
+ # lib/sqa/strategry/common.rb
2
+
3
+ # This module needs to be extend'ed within
4
+ # a strategy class so that these common class
5
+ # methods are available in every trading strategy.
6
+
7
+ class SQA::Strategy
8
+ module Common
9
+ def trade_against(vector)
10
+ return :hold unless respond_to? :trade
11
+
12
+ recommendation = trade(vector)
13
+
14
+ if :sell == recommendation
15
+ :buy
16
+ elsif :buy == recommendation
17
+ :sell
18
+ else
19
+ :hold
20
+ end
21
+ end
22
+
23
+ def desc
24
+ doc_filename = self.name.split('::').last.downcase + ".md"
25
+ doc_path = Pathname.new(__dir__) + doc_filename
26
+
27
+ debug_me{[ :doc_path ]}
28
+
29
+ if doc_path.exist?
30
+ doc = doc_path.read
31
+ else
32
+ doc = "A description of #{self.name} is not available"
33
+ end
34
+
35
+ puts doc
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,43 @@
1
+ # lib/sqa/strategry/consensus.rb
2
+
3
+ require_relative 'common'
4
+
5
+ class SQA::Strategy::Consensus
6
+ extend SQA::Strategy::Common
7
+
8
+ def self.trade(vector)
9
+ new(vector).my_fancy_trader
10
+ end
11
+
12
+ def initialize(vector)
13
+ @vector = vector
14
+ @results = []
15
+ end
16
+
17
+ def my_fancy_trader
18
+ strat_one
19
+ strat_two
20
+ strat_three
21
+ strat_four
22
+ strat_five
23
+ consensus
24
+ end
25
+
26
+ def consensus
27
+ count = @results.group_by(&:itself).transform_values(&:count)
28
+
29
+ if count[:buy] > count[:sell]
30
+ :buy
31
+ elsif count[:sell] > count[:buy]
32
+ :sell
33
+ else
34
+ :hold
35
+ end
36
+ end
37
+
38
+ def strat_one = @results << (0==rand(2) ? :buy : :sell)
39
+ def strat_two = @results << (0==rand(2) ? :buy : :sell)
40
+ def strat_three = @results << (0==rand(2) ? :buy : :sell)
41
+ def strat_four = @results << (0==rand(2) ? :buy : :sell)
42
+ def strat_five = @results << :hold
43
+ end
@@ -0,0 +1,19 @@
1
+ # lib/sqa/strategry/ema.rb
2
+
3
+ require_relative 'common'
4
+
5
+ class SQA::Strategy::EMA
6
+ extend SQA::Strategy::Common
7
+
8
+ def self.trade(vector)
9
+ ema_trend = vector.ema[:trend]
10
+
11
+ if :up == ema_trend
12
+ :buy
13
+ elsif :down == ema_trend
14
+ :sell
15
+ else
16
+ :hold
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # lib/sqa/strategry/mp.rb
2
+
3
+ require_relative 'common'
4
+
5
+ class SQA::Strategy::MP
6
+ extend SQA::Strategy::Common
7
+
8
+ def self.trade(vector)
9
+ mp = vector.market_profile=:mixed,
10
+
11
+ if :resistance == mp
12
+ :sell
13
+ elsif :support == mp
14
+ :buy
15
+ else
16
+ :hold
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # lib/sqa/strategry/mr.rb
2
+
3
+ require_relative 'common'
4
+
5
+ class SQA::Strategy::MR
6
+ extend SQA::Strategy::Common
7
+
8
+ def self.trade(vector)
9
+ if vector.mr
10
+ :sell
11
+ else
12
+ :hold
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # SQA::Strategy::Random
2
+
3
+ A random flip of a three headed coin.
4
+
5
+ Responds with a :buy, :sell or :hold recommendation based upon a random number. Out of 9 possible random numbers, the lower third, middle third and upper third of the number set are used to determine the recommendation.
@@ -0,0 +1,18 @@
1
+ # lib/sqa/strategry/random.rb
2
+
3
+ require_relative 'common'
4
+
5
+ class SQA::Strategy::Random
6
+ extend SQA::Strategy::Common
7
+
8
+ def self.trade(vector)
9
+ case rand(9)
10
+ when (0..2)
11
+ :buy
12
+ when (3..5)
13
+ :sell
14
+ else
15
+ :hold
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ # lib/sqa/strategry/rsi.rb
2
+
3
+ require_relative 'common'
4
+
5
+ class SQA::Strategy::RSI
6
+ extend SQA::Strategy::Common
7
+
8
+ def self.trade(vector)
9
+ rsi_trend = vector.rsi[:trend]
10
+
11
+ if :over_bought == rsi_trend
12
+ :sell
13
+ elsif :over_sold == rsi_trend
14
+ :buy
15
+ else
16
+ :hold
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # lib/sqa/strategry/sma.rb
2
+
3
+ require_relative 'common'
4
+
5
+ class SQA::Strategy::SMA
6
+ extend SQA::Strategy::Common
7
+
8
+ def self.trade(vector)
9
+ sma_trend = vector.rsi[:trend]
10
+
11
+ if :up == sma_trend
12
+ :buy
13
+ elsif :down == sma_trend
14
+ :sell
15
+ else
16
+ :hold
17
+ end
18
+ end
19
+ end
data/lib/sqa/strategy.rb CHANGED
@@ -7,9 +7,16 @@ class SQA::Strategy
7
7
  @strategies = []
8
8
  end
9
9
 
10
- def add(a_proc=nil, &block)
11
- @strategies << a_proc unless a_proc.nil?
12
- @strategies << block if a_proc.nil? && block_given?
10
+ def add(a_strategy)
11
+ raise SQA::BadParameterError unless [Class, Method].include? a_strategy.class
12
+
13
+ a_proc = if Class == a_strategy.class
14
+ a_strategy.method(:trade)
15
+ else
16
+ a_strategy
17
+ end
18
+
19
+ @strategies << a_proc
13
20
  end
14
21
 
15
22
  def execute(v)
@@ -18,48 +25,33 @@ class SQA::Strategy
18
25
  @strategies.each { |signal| result << signal.call(v) }
19
26
  result
20
27
  end
21
- end
22
28
 
23
- __END__
29
+ def auto_load(except: [:common], only: [])
30
+ dir_path = Pathname.new(__dir__) + "strategy"
31
+ except = Array(except).map{|f| f.to_s.downcase}
32
+ only = Array(only).map{|f| f.to_s.downcase}
24
33
 
25
- Example Usage
26
- =============
34
+ dir_path.children.each do |child|
35
+ next unless ".rb" == child.extname.downcase
27
36
 
28
- ss = SQA::Strategy.new
37
+ basename = child.basename.to_s.split('.').first.downcase
29
38
 
30
- ss.add do |vector|
31
- case rand(10)
32
- when (8..)
33
- :buy
34
- when (..3)
35
- :sell
36
- else
37
- :hold
38
- end
39
- end
39
+ next if except.include? basename
40
+ next if !only.empty? && !only.include?(basename)
40
41
 
42
+ print "loading #{basename} ... "
43
+ load child
44
+ puts "done"
45
+ end
41
46
 
42
- ss.add do |vector|
43
- case rand(10)
44
- when (8..)
45
- :sell
46
- when (..3)
47
- :buy
48
- else
49
- :keep
47
+ nil
50
48
  end
51
- end
52
-
53
- def magic(vector)
54
- 0 == rand(2) ? :spend : :save
55
- end
56
49
 
57
- ss.add method(:magic)
58
-
59
- class MyClass
60
- def self.my_method(vector)
61
- vector.rsi[:rsi]
50
+ def available
51
+ ObjectSpace.each_object(Class).select { |klass|
52
+ klass.to_s.start_with?("SQA::Strategy::")
53
+ }
62
54
  end
63
55
  end
64
56
 
65
- ss.add MyClass.method(:my_method)
57
+
data/lib/sqa/trade.rb ADDED
@@ -0,0 +1,24 @@
1
+ # lib/sqa/trade.rb
2
+
3
+
4
+ class SQA::Trade
5
+ attr_accessor :df
6
+
7
+ def initialize(filename="trades.csv")
8
+ @df = SQA::DataFrame.load(filename)
9
+ end
10
+
11
+ def place(signal, ticker, shares, price=nil)
12
+ # TODO: insert row into @df
13
+
14
+ uuid = rand(100000) # FIXME: place holder
15
+ end
16
+
17
+ def confirm(uuid, shares, price)
18
+ # TODO: update the row in the data frame
19
+ end
20
+
21
+ def save
22
+ # TODO: save the data frame
23
+ end
24
+ end
data/lib/sqa/version.rb CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SQA
4
4
  module Version
5
- VERSION = "0.0.3"
5
+ VERSION = "0.0.5"
6
6
  end
7
7
  end
data/lib/sqa.rb CHANGED
@@ -4,10 +4,6 @@ require 'active_support'
4
4
  require 'active_support/core_ext/string'
5
5
  require 'daru'
6
6
  require 'date'
7
-
8
- require 'debug_me'
9
- include DebugMe
10
-
11
7
  require 'descriptive_statistics'
12
8
  require 'mixlib/config'
13
9
  require 'nenv'
@@ -20,6 +16,22 @@ end
20
16
 
21
17
 
22
18
  module SQA
19
+ Signal = {
20
+ hold: 0,
21
+ buy: 1,
22
+ sell: 2
23
+ }.freeze
24
+
25
+ Trend = {
26
+ up: 0,
27
+ down: 1
28
+ }.freeze
29
+
30
+ Swing = {
31
+ valley: 0,
32
+ peak: 1,
33
+ }.freeze
34
+
23
35
  module Config
24
36
  extend Mixlib::Config
25
37
  config_strict_mode true
@@ -40,8 +52,10 @@ end
40
52
  require_relative "sqa/data_frame"
41
53
  require_relative "sqa/errors"
42
54
  require_relative "sqa/indicator"
55
+ require_relative "sqa/portfolio"
43
56
  require_relative "sqa/strategy"
44
57
  require_relative "sqa/stock"
58
+ require_relative "sqa/trade"
45
59
  require_relative "sqa/version"
46
60
 
47
61
 
metadata CHANGED
@@ -1,15 +1,183 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
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-17 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2023-08-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: active_support
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: daru
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: descriptive_statistics
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: gruff
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mixlib-config
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: nenv
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: version_gem
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: amazing_print
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: bundler
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: debug_me
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: minitest
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rake
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
13
181
  description: Simplistic playpen (e.g. not for serious use) for doing technical analysis
14
182
  of stock prices.
15
183
  email:
@@ -20,7 +188,6 @@ extensions: []
20
188
  extra_rdoc_files: []
21
189
  files:
22
190
  - ".envrc"
23
- - ".irbrc"
24
191
  - CHANGELOG.md
25
192
  - LICENSE
26
193
  - README.md
@@ -28,6 +195,9 @@ files:
28
195
  - bin/sqa
29
196
  - checksums/sqa-0.0.1.gem.sha512
30
197
  - checksums/sqa-0.0.2.gem.sha512
198
+ - checksums/sqa-0.0.3.gem.sha512
199
+ - checksums/sqa-0.0.4.gem.sha512
200
+ - checksums/sqa-0.0.5.gem.sha512
31
201
  - docs/README.md
32
202
  - docs/average_true_range.md
33
203
  - docs/bollinger_bands.md
@@ -77,9 +247,20 @@ files:
77
247
  - lib/sqa/indicator/simple_moving_average_trend.rb
78
248
  - lib/sqa/indicator/stochastic_oscillator.rb
79
249
  - lib/sqa/indicator/true_range.rb
80
- - lib/sqa/protfolio.rb
250
+ - lib/sqa/portfolio.rb
81
251
  - lib/sqa/stock.rb
82
252
  - lib/sqa/strategy.rb
253
+ - lib/sqa/strategy/README.md
254
+ - lib/sqa/strategy/common.rb
255
+ - lib/sqa/strategy/consensus.rb
256
+ - lib/sqa/strategy/ema.rb
257
+ - lib/sqa/strategy/mp.rb
258
+ - lib/sqa/strategy/mr.rb
259
+ - lib/sqa/strategy/random.md
260
+ - lib/sqa/strategy/random.rb
261
+ - lib/sqa/strategy/rsi.rb
262
+ - lib/sqa/strategy/sma.rb
263
+ - lib/sqa/trade.rb
83
264
  - lib/sqa/version.rb
84
265
  homepage: https://github.com/MadBomber/sqa
85
266
  licenses:
data/.irbrc DELETED
@@ -1,3 +0,0 @@
1
- # sqa/,urg
2
-
3
- require 'sqa'
data/lib/sqa/protfolio.rb DELETED
@@ -1,8 +0,0 @@
1
- # lib/sqa/portfolio.rb
2
-
3
- # A collection of stocks
4
- # primary id is ticker its unique
5
-
6
- class SQA::Portfolio < ActiveRecord::Base
7
- has_many :stocks # use ticker as the foreign key
8
- end