sqa 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.envrc +4 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +21 -0
- data/README.md +29 -0
- data/Rakefile +4 -0
- data/bin/sqa +6 -0
- data/checksums/sqa-0.0.1.gem.sha512 +1 -0
- data/docs/requirements.md +40 -0
- data/lib/sqa/activity.rb +10 -0
- data/lib/sqa/cli.rb +310 -0
- data/lib/sqa/datastore/active_record.rb +89 -0
- data/lib/sqa/datastore/csv/yahoo_finance.rb +51 -0
- data/lib/sqa/datastore/csv.rb +93 -0
- data/lib/sqa/datastore/sqlite.rb +7 -0
- data/lib/sqa/datastore.rb +6 -0
- data/lib/sqa/errors.rb +5 -0
- data/lib/sqa/indicator/README.md +33 -0
- data/lib/sqa/indicator/average_true_range.md +9 -0
- data/lib/sqa/indicator/average_true_range.rb +30 -0
- data/lib/sqa/indicator/bollinger_bands.md +15 -0
- data/lib/sqa/indicator/bollinger_bands.rb +28 -0
- data/lib/sqa/indicator/candlestick_pattern_recognizer.md +4 -0
- data/lib/sqa/indicator/candlestick_pattern_recognizer.rb +60 -0
- data/lib/sqa/indicator/classify_market_profile.md +4 -0
- data/lib/sqa/indicator/classify_market_profile.rb +33 -0
- data/lib/sqa/indicator/donchian_channel.md +5 -0
- data/lib/sqa/indicator/donchian_channel.rb +29 -0
- data/lib/sqa/indicator/double_top_bottom_pattern.md +3 -0
- data/lib/sqa/indicator/double_top_bottom_pattern.rb +34 -0
- data/lib/sqa/indicator/ema_analysis.md +19 -0
- data/lib/sqa/indicator/ema_analysis.rb +70 -0
- data/lib/sqa/indicator/fibonacci_retracement.md +3 -0
- data/lib/sqa/indicator/fibonacci_retracement.rb +25 -0
- data/lib/sqa/indicator/head_and_shoulders_pattern.md +3 -0
- data/lib/sqa/indicator/head_and_shoulders_pattern.rb +26 -0
- data/lib/sqa/indicator/identify_wave_condition.md +6 -0
- data/lib/sqa/indicator/identify_wave_condition.rb +40 -0
- data/lib/sqa/indicator/mean_reversion.md +8 -0
- data/lib/sqa/indicator/mean_reversion.rb +37 -0
- data/lib/sqa/indicator/momentum.md +19 -0
- data/lib/sqa/indicator/momentum.rb +26 -0
- data/lib/sqa/indicator/moving_average_convergence_divergence.md +23 -0
- data/lib/sqa/indicator/moving_average_convergence_divergence.rb +25 -0
- data/lib/sqa/indicator/relative_strength_index.md +6 -0
- data/lib/sqa/indicator/relative_strength_index.md.rb +47 -0
- data/lib/sqa/indicator/simple_moving_average.md +8 -0
- data/lib/sqa/indicator/simple_moving_average.rb +21 -0
- data/lib/sqa/indicator/simple_moving_average_trend.rb +31 -0
- data/lib/sqa/indicator/stochastic_oscillator.md +5 -0
- data/lib/sqa/indicator/stochastic_oscillator.rb +39 -0
- data/lib/sqa/indicator/true_range.md +12 -0
- data/lib/sqa/indicator/true_range.rb +37 -0
- data/lib/sqa/indicator.rb +11 -0
- data/lib/sqa/protfolio.rb +8 -0
- data/lib/sqa/stock.rb +29 -0
- data/lib/sqa/version.rb +5 -0
- data/lib/sqa.rb +12 -0
- metadata +105 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
# lib/sqa/indicator/moving_average_convergence_divergence.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def moving_average_convergence_divergence(
|
6
|
+
prices,
|
7
|
+
short_period,
|
8
|
+
long_period,
|
9
|
+
signal_period
|
10
|
+
)
|
11
|
+
|
12
|
+
short_ma = simple_moving_average(prices, short_period)
|
13
|
+
long_ma = simple_moving_average(prices, long_period)
|
14
|
+
macd_line = short_ma.last - long_ma.last
|
15
|
+
signal_line = simple_moving_average(short_ma, signal_period).last
|
16
|
+
|
17
|
+
{
|
18
|
+
macd: macd_line, # Array
|
19
|
+
signal: signal_line # Array
|
20
|
+
}
|
21
|
+
end
|
22
|
+
alias_method :macd, :moving_average_convergence_divergence
|
23
|
+
|
24
|
+
end; end
|
25
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Relative Strength Index (RSI)
|
2
|
+
|
3
|
+
This method takes in an array of historical prices for a stock and a period (the number of days to calculate the RSI over). It uses the `each_cons` method to iterate over a sliding window of closing prices and calculate the gains and losses for each window. Then, it calculates the average gain and average loss for the time period and uses these values to calculate the RSI. The method returns the RSI value for the given period.
|
4
|
+
|
5
|
+
* over_bought if rsi >= 70
|
6
|
+
* over_sold if rsi <= 30
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# lib/sqa/indicator/relative_strength_index.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def relative_strength_index(
|
6
|
+
prices, # Array of prices
|
7
|
+
period, # Integer how many to consider at a time
|
8
|
+
over_sold = 30.0, # Float break over point in trend
|
9
|
+
over_boufht = 70.0 # Float break over point in trend
|
10
|
+
)
|
11
|
+
gains = []
|
12
|
+
losses = []
|
13
|
+
|
14
|
+
prices.each_cons(2) do |pair|
|
15
|
+
change = pair[1] - pair[0]
|
16
|
+
|
17
|
+
if change > 0
|
18
|
+
gains << change
|
19
|
+
losses << 0
|
20
|
+
else
|
21
|
+
gains << 0
|
22
|
+
losses << change.abs
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
avg_gain = gains.last(period).sum / period.to_f
|
27
|
+
avg_loss = losses.last(period).sum / period.to_f
|
28
|
+
rs = avg_gain / avg_loss
|
29
|
+
rsi = 100 - (100 / (1 + rs))
|
30
|
+
|
31
|
+
trend = if rsi >= over_bought
|
32
|
+
:over_bought
|
33
|
+
elsif rsi <= over_sold
|
34
|
+
:over_sold
|
35
|
+
else
|
36
|
+
:normal
|
37
|
+
end
|
38
|
+
|
39
|
+
{
|
40
|
+
rsi: rsi, # Float
|
41
|
+
trend: trend # Symbol :normal, :over_bought, :over+sold
|
42
|
+
}
|
43
|
+
end
|
44
|
+
alias_method :rsi, :relative_strength_index
|
45
|
+
|
46
|
+
end; end
|
47
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Simple Moving Average (SMA)
|
2
|
+
|
3
|
+
This method takes in an array of historical prices for a stock and a period (the number of days to calculate the moving average over). It uses the `each_cons` method to iterate over a sliding window of closing prices and calculate the moving average for each window. The method returns an array of the moving averages for each windo
|
4
|
+
|
5
|
+
# Simple Moving Average Trend
|
6
|
+
|
7
|
+
Up or down with angle to indicate how steep the movement is.
|
8
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# lib/sqa/indicator/simple_moving_average.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def simple_moving_average(
|
6
|
+
prices, # Array of prices
|
7
|
+
period # Integer how many to consider at a time
|
8
|
+
)
|
9
|
+
moving_averages = []
|
10
|
+
|
11
|
+
prices.each_cons(period) do |window|
|
12
|
+
moving_average = window.sum / period.to_f
|
13
|
+
moving_averages << moving_average
|
14
|
+
end
|
15
|
+
|
16
|
+
moving_averages # Array
|
17
|
+
end
|
18
|
+
alias_method :sma, :simple_moving_average
|
19
|
+
|
20
|
+
end; end
|
21
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# lib/sqa/indicator/simple_moving_average_trend.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def simple_moving_average_trend(
|
6
|
+
closing_prices, # Array of closing prices
|
7
|
+
period, # Integer number of entries to consider
|
8
|
+
delta = 0.0005 # Float defines a :nutria trend range.
|
9
|
+
)
|
10
|
+
sma = simple_moving_average(closing_prices, period)
|
11
|
+
last_sma = sma.last
|
12
|
+
prev_sma = sma[-2]
|
13
|
+
angle = Math.atan((last_sma - prev_sma) / period) * (180 / Math::PI)
|
14
|
+
|
15
|
+
if angle > 0.0
|
16
|
+
trend = :up
|
17
|
+
elsif angle < 0.0
|
18
|
+
trend = :down
|
19
|
+
else
|
20
|
+
trend = :neutral
|
21
|
+
end
|
22
|
+
|
23
|
+
{
|
24
|
+
trend: trend, # Symbol :up, :down, :neutral
|
25
|
+
angle: angle # Float how step the trend
|
26
|
+
}
|
27
|
+
end
|
28
|
+
alias_method :sma_trend, :simple_moving_average_trend
|
29
|
+
|
30
|
+
end; end
|
31
|
+
|
@@ -0,0 +1,5 @@
|
|
1
|
+
# Stochastic Oscillator
|
2
|
+
|
3
|
+
Calculates the Stochastic Oscillator for a given set of price data.
|
4
|
+
|
5
|
+
Stochastic Oscillator: The Stochastic Oscillator compares a security's closing price to its price range over a specified period. It helps identify potential trend reversals and overbought/oversold conditions.
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# lib/sqa/indicator/stochastic_oscillator.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
# @param high_prices [Array]
|
6
|
+
# @param low_prices [Array]
|
7
|
+
# @param close_prices [Array]
|
8
|
+
# @param period [Integer]
|
9
|
+
# @param smoothing_period [Integer]
|
10
|
+
#
|
11
|
+
# @return [Array] An array of %K and %D values.
|
12
|
+
#
|
13
|
+
def stochastic_oscillator(
|
14
|
+
high_prices, # Array of high prices
|
15
|
+
low_prices, # Array of low prices
|
16
|
+
closing_prices, # Array of closing prices
|
17
|
+
period, # Integer The period for calculating the Stochastic Oscillator
|
18
|
+
smoothing_period # Integer The smoothing period for %K line
|
19
|
+
)
|
20
|
+
k_values = []
|
21
|
+
d_values = []
|
22
|
+
|
23
|
+
closing_prices.each_cons(period) do |closing_prices_subset|
|
24
|
+
highest_high = high_prices.max(period)
|
25
|
+
lowest_low = low_prices.min(period)
|
26
|
+
current_close = closing_prices_subset.last
|
27
|
+
k_values << (current_close - lowest_low) / (highest_high - lowest_low) * 100 # Calculate the k_value
|
28
|
+
end
|
29
|
+
|
30
|
+
k_values.each_cons(smoothing_period) do |k_values_subset|
|
31
|
+
d_values << k_values_subset.sum / smoothing_period.to_f # Calculate the d_value
|
32
|
+
end
|
33
|
+
|
34
|
+
[k_values, d_values]
|
35
|
+
end
|
36
|
+
alias_method :so, :stochastic_oscillator
|
37
|
+
|
38
|
+
end; end
|
39
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# True Range
|
2
|
+
|
3
|
+
Calculates the True Range (TR) for a given set of price data.
|
4
|
+
|
5
|
+
The True Range is a measure of the price volatility of a security over a given period. It is calculated as the greatest of the following three values:
|
6
|
+
|
7
|
+
* The difference between the current high and the current low.
|
8
|
+
* The absolute value of the difference between the current high and the previous close.
|
9
|
+
* The absolute value of the difference between the current low and the previous close.
|
10
|
+
|
11
|
+
The True Range helps to capture the true extent of price movement, taking into account potential gaps or price jumps between periods. It is often used as a component in calculating other indicators, such as the Average True Range.
|
12
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# lib/sqa/indicator/true_range.rb
|
2
|
+
|
3
|
+
# See Also: average_true_range
|
4
|
+
|
5
|
+
module SQA::Indicator; class << self
|
6
|
+
|
7
|
+
# @param high_prices [Array]
|
8
|
+
# @param low_prices [Array]
|
9
|
+
# @param previous_closes [Array]
|
10
|
+
#
|
11
|
+
# @return [Array]
|
12
|
+
#
|
13
|
+
def true_range(
|
14
|
+
high_prices, # Array of high prices
|
15
|
+
low_prices, # Array of low prices
|
16
|
+
previous_closes # Array of previous closing prices
|
17
|
+
)
|
18
|
+
true_ranges = []
|
19
|
+
|
20
|
+
high_prices.each_with_index do |high, index|
|
21
|
+
low = low_prices[index]
|
22
|
+
previous_close = previous_closes[index]
|
23
|
+
|
24
|
+
true_range = [
|
25
|
+
high - low,
|
26
|
+
(high - previous_close).abs,
|
27
|
+
(low - previous_close).abs
|
28
|
+
].max
|
29
|
+
|
30
|
+
true_ranges << true_range
|
31
|
+
end
|
32
|
+
|
33
|
+
true_ranges # Array of True Range values
|
34
|
+
end
|
35
|
+
alias_method :tr, :true_range
|
36
|
+
|
37
|
+
end; end
|
data/lib/sqa/stock.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# lib/sqa/stock.rb
|
2
|
+
|
3
|
+
require_relative 'indicators'
|
4
|
+
require_relative 'datastore'
|
5
|
+
|
6
|
+
class SQA::Stock < ActiveRecord::Base
|
7
|
+
include SQA::Indicators
|
8
|
+
|
9
|
+
# has_many :activities using ticker as the foreign key
|
10
|
+
# primary id is ticker it is unique
|
11
|
+
|
12
|
+
attr_accessor :company_name
|
13
|
+
attr_accessor :data
|
14
|
+
attr_accessor :ticker
|
15
|
+
|
16
|
+
def initialize(ticker, datastore = SQA::Datastore::CSV)
|
17
|
+
@ticker = ticker
|
18
|
+
@company_name = "Company Name"
|
19
|
+
@data = datastore.new(ticker)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"#{ticker} with #{@data.size} data points."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
__END__
|
28
|
+
|
29
|
+
aapl = Stock.new('aapl', SQA::Datastore::CSV)
|
data/lib/sqa/version.rb
ADDED
data/lib/sqa.rb
ADDED
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqa
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dewayne VanHoozer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-08-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Simplistic playpen (e.g. not for serious use) for doing technical analysis
|
14
|
+
of stock prices.
|
15
|
+
email:
|
16
|
+
- dvanhoozer@gmail.com
|
17
|
+
executables:
|
18
|
+
- sqa
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- ".envrc"
|
23
|
+
- CHANGELOG.md
|
24
|
+
- LICENSE
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- bin/sqa
|
28
|
+
- checksums/sqa-0.0.1.gem.sha512
|
29
|
+
- docs/requirements.md
|
30
|
+
- lib/sqa.rb
|
31
|
+
- lib/sqa/activity.rb
|
32
|
+
- lib/sqa/cli.rb
|
33
|
+
- lib/sqa/datastore.rb
|
34
|
+
- lib/sqa/datastore/active_record.rb
|
35
|
+
- lib/sqa/datastore/csv.rb
|
36
|
+
- lib/sqa/datastore/csv/yahoo_finance.rb
|
37
|
+
- lib/sqa/datastore/sqlite.rb
|
38
|
+
- lib/sqa/errors.rb
|
39
|
+
- lib/sqa/indicator.rb
|
40
|
+
- lib/sqa/indicator/README.md
|
41
|
+
- lib/sqa/indicator/average_true_range.md
|
42
|
+
- lib/sqa/indicator/average_true_range.rb
|
43
|
+
- lib/sqa/indicator/bollinger_bands.md
|
44
|
+
- lib/sqa/indicator/bollinger_bands.rb
|
45
|
+
- lib/sqa/indicator/candlestick_pattern_recognizer.md
|
46
|
+
- lib/sqa/indicator/candlestick_pattern_recognizer.rb
|
47
|
+
- lib/sqa/indicator/classify_market_profile.md
|
48
|
+
- lib/sqa/indicator/classify_market_profile.rb
|
49
|
+
- lib/sqa/indicator/donchian_channel.md
|
50
|
+
- lib/sqa/indicator/donchian_channel.rb
|
51
|
+
- lib/sqa/indicator/double_top_bottom_pattern.md
|
52
|
+
- lib/sqa/indicator/double_top_bottom_pattern.rb
|
53
|
+
- lib/sqa/indicator/ema_analysis.md
|
54
|
+
- lib/sqa/indicator/ema_analysis.rb
|
55
|
+
- lib/sqa/indicator/fibonacci_retracement.md
|
56
|
+
- lib/sqa/indicator/fibonacci_retracement.rb
|
57
|
+
- lib/sqa/indicator/head_and_shoulders_pattern.md
|
58
|
+
- lib/sqa/indicator/head_and_shoulders_pattern.rb
|
59
|
+
- lib/sqa/indicator/identify_wave_condition.md
|
60
|
+
- lib/sqa/indicator/identify_wave_condition.rb
|
61
|
+
- lib/sqa/indicator/mean_reversion.md
|
62
|
+
- lib/sqa/indicator/mean_reversion.rb
|
63
|
+
- lib/sqa/indicator/momentum.md
|
64
|
+
- lib/sqa/indicator/momentum.rb
|
65
|
+
- lib/sqa/indicator/moving_average_convergence_divergence.md
|
66
|
+
- lib/sqa/indicator/moving_average_convergence_divergence.rb
|
67
|
+
- lib/sqa/indicator/relative_strength_index.md
|
68
|
+
- lib/sqa/indicator/relative_strength_index.md.rb
|
69
|
+
- lib/sqa/indicator/simple_moving_average.md
|
70
|
+
- lib/sqa/indicator/simple_moving_average.rb
|
71
|
+
- lib/sqa/indicator/simple_moving_average_trend.rb
|
72
|
+
- lib/sqa/indicator/stochastic_oscillator.md
|
73
|
+
- lib/sqa/indicator/stochastic_oscillator.rb
|
74
|
+
- lib/sqa/indicator/true_range.md
|
75
|
+
- lib/sqa/indicator/true_range.rb
|
76
|
+
- lib/sqa/protfolio.rb
|
77
|
+
- lib/sqa/stock.rb
|
78
|
+
- lib/sqa/version.rb
|
79
|
+
homepage: https://github.com/MadBomber/sqa
|
80
|
+
licenses:
|
81
|
+
- MIT
|
82
|
+
metadata:
|
83
|
+
allowed_push_host: https://rubygems.org
|
84
|
+
homepage_uri: https://github.com/MadBomber/sqa
|
85
|
+
source_code_uri: https://github.com/MadBomber/sta
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '2.7'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubygems_version: 3.4.18
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: sqa - Stock Qualitative Analysis
|
105
|
+
test_files: []
|