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
data/lib/sqa/errors.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Indicators
|
2
|
+
|
3
|
+
An indicator is a formula/metric on a stock's historical activity. It is presumed to be a forecast as to what the stock activity might be in the future. A single indicator is not necessarily an accurate predictor of future events not is any specific group of indicators.
|
4
|
+
|
5
|
+
In other words the future is uncertain. Is it a coin flip? Heads the stock's price goes up. Tails, the stock's price goes down. Its one or the other right? What if the price never changes. Then its not a coin flip. Also what is the time frame involved in the forecast? Is it tomorrow, next week, next month, next year, next decade? What is the delta change in price that can be expected?
|
6
|
+
|
7
|
+
So indicators are like TV weather forecastors. Sometimes they are right. Sometimes they are wrong.
|
8
|
+
|
9
|
+
We are dealing with uncertainity. In uncertainity there is chaos. If it is possible to be right more times that you are wrong you can make money. If you are always wrong then always do the opposite and you will make money. When you are wrong more times than you are right.... you loose.
|
10
|
+
|
11
|
+
Its a game. Game theory tells us that there are winners and losers. Bookies at the track make money every day by taking a cut of the losers loses before giving them to the winners. Bookies always win so long as they keep their books balanced. Accounts are important.
|
12
|
+
|
13
|
+
Back to indicators. Here is a list of the current indicators:
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
* [Average True Range](average true range.md)
|
18
|
+
* [Bollinger Bands](bollinger bands.md)
|
19
|
+
* [Vandlestick Pattern Recognizer](candlestick pattern recognizer.md)
|
20
|
+
* [Vlassify Market Profile](classify market profile.md)
|
21
|
+
* [Donchian Channel](donchian channel.md)
|
22
|
+
* [Double Top Bottom Pattern](double top bottom pattern.md)
|
23
|
+
* [EMA Analysis](ema analysis.md)
|
24
|
+
* [Fibonacci Retracement](fibonacci retracement.md)
|
25
|
+
* [Head and Shoulders Pattern](head and shoulders pattern.md)
|
26
|
+
* [Identify Wave Condition](identify wave condition.md)
|
27
|
+
* [MACD](macd.md)
|
28
|
+
* [Mean Reversion](mean reversion.md)
|
29
|
+
* [Momentum](momentum.md)
|
30
|
+
* [RSI](rsi.md)
|
31
|
+
* [Simple Moving Average](simple moving average.md)
|
32
|
+
* [Stochastic Oscillator](stochastic oscillator.md)
|
33
|
+
* [True Range](true range.md)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Average True Range
|
2
|
+
|
3
|
+
Calculates the Average True Range (ATR) for a given set of price data.
|
4
|
+
|
5
|
+
The Average True Range is an indicator that calculates the average of the True Range values over a specified period. It provides a measure of the average volatility of a security over that period.
|
6
|
+
|
7
|
+
The ATR is commonly used to assess the volatility of a security, identify potential trend reversals, and determine appropriate stop-loss levels. Higher ATR values indicate higher volatility, while lower ATR values indicate lower volatility.
|
8
|
+
|
9
|
+
For example, a 14-day Average True Range would calculate the average of the True Range values over the past 14 trading days. Traders and analysts may use this indicator to set stop-loss levels based on the average volatility of the security.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# lib/sqa/indicator/average_true_range.rb
|
2
|
+
|
3
|
+
# See Also: true_range
|
4
|
+
|
5
|
+
module SQA::Indicator; class << self
|
6
|
+
|
7
|
+
def average_true_range(
|
8
|
+
high_prices, # Array of the day's high price
|
9
|
+
low_prices, # Array of the day's low price
|
10
|
+
close_prices, # Array of the day's closing price
|
11
|
+
period # Integer the number of days to consider
|
12
|
+
)
|
13
|
+
true_ranges = true_range(high_prices, low_prices, close_prices)
|
14
|
+
atr_values = []
|
15
|
+
|
16
|
+
true_ranges.each_with_index do |true_range, index|
|
17
|
+
if index < period - 1
|
18
|
+
atr_values << nil
|
19
|
+
elsif index == period - 1
|
20
|
+
atr_values << true_ranges[0..index].sum / period.to_f
|
21
|
+
else
|
22
|
+
atr_values << (atr_values[index - 1] * (period - 1) + true_range) / period.to_f
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
atr_values # Array
|
27
|
+
end
|
28
|
+
alias_method :atr, :average_true_range
|
29
|
+
|
30
|
+
end; end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# Bollinger Bands
|
4
|
+
|
5
|
+
This method takes in an array of historical prices for a stock, a period (the number of days to calculate the moving average and standard deviation over), and the number of standard deviations to use for the upper and lower Bollinger Bands. It uses the `moving_averages` method to calculate the moving average for the given period, and then calculates the standard deviation of the closing prices for each window of the given period. Finally, it calculates the upper and lower Bollinger Bands based on the moving average and standard deviation, and returns an array containing the upper and lower bands.
|
6
|
+
|
7
|
+
The `num_std_dev` parameter in the Bollinger Bands method specifies the number of standard deviations to use for the upper and lower bands. The default value for this parameter can depend on the specific security being analyzed and the time period being used.
|
8
|
+
|
9
|
+
A common default value for `num_std_dev` is 2, which corresponds to the standard deviation of the price data over the given time period. Using a value of 2 for `num_std_dev` will result in the upper and lower bands being placed at a distance of two standard deviations from the moving average.
|
10
|
+
|
11
|
+
However, the optimal value for `num_std_dev` can vary depending on the volatility of the security being analyzed. For highly volatile securities, a larger value for `num_std_dev` may be more appropriate, while for less volatile securities, a smaller value may be more appropriate.
|
12
|
+
|
13
|
+
Ultimately, the best default value for `num_std_dev` will depend on the specific use case and should be chosen based on the characteristics of the security being analyzed and the preferences of the analyst.
|
14
|
+
|
15
|
+
The difference between the upper and lower bands can be an indicator of how volatile the stock is.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# lib/sqa/indicator/bollinger_bands.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def bollinger_bands(
|
6
|
+
prices, # Array of prices
|
7
|
+
period, # Integer number of entries to consider
|
8
|
+
num_std_devs=2 # Integer number of standard deviations
|
9
|
+
)
|
10
|
+
moving_averages = simple_moving_average(prices, period)
|
11
|
+
standard_deviations = []
|
12
|
+
|
13
|
+
prices.each_cons(period) do |window|
|
14
|
+
standard_deviation = Math.sqrt(window.map { |price| (price - moving_averages.last) ** 2 }.sum / period)
|
15
|
+
standard_deviations << standard_deviation
|
16
|
+
end
|
17
|
+
|
18
|
+
upper_band = moving_averages.last + (num_std_devs * standard_deviations.last)
|
19
|
+
lower_band = moving_averages.last - (num_std_devs * standard_deviations.last)
|
20
|
+
|
21
|
+
{
|
22
|
+
upper_band: upper_band, # Array
|
23
|
+
;pwer_band: lower_band # Array
|
24
|
+
}
|
25
|
+
end
|
26
|
+
alias_method :bb, :bollinger_bands
|
27
|
+
|
28
|
+
end; end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# lib/sqa/indicator/candlestick_pattern_recognizer.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def candlestick_pattern_recognizer(
|
6
|
+
open_prices, # Array day's ppen price
|
7
|
+
high_prices, # Array day's high price
|
8
|
+
low_prices, # Array day's low price
|
9
|
+
close_prices # Array day's closing price
|
10
|
+
)
|
11
|
+
patterns = []
|
12
|
+
|
13
|
+
close_prices.each_with_index do |close, index|
|
14
|
+
if index >= 2
|
15
|
+
previous_close = close_prices[index - 1]
|
16
|
+
previous_open = open_prices[index - 1]
|
17
|
+
previous_high = high_prices[index - 1]
|
18
|
+
previous_low = low_prices[index - 1]
|
19
|
+
|
20
|
+
second_previous_close = close_prices[index - 2]
|
21
|
+
second_previous_open = open_prices[index - 2]
|
22
|
+
second_previous_high = high_prices[index - 2]
|
23
|
+
second_previous_low = low_prices[index - 2]
|
24
|
+
|
25
|
+
if close > previous_close &&
|
26
|
+
previous_close < previous_open &&
|
27
|
+
close < previous_open &&
|
28
|
+
close > previous_low &&
|
29
|
+
close > second_previous_close
|
30
|
+
patterns << :bullish_engulfing
|
31
|
+
|
32
|
+
elsif close < previous_close &&
|
33
|
+
previous_close > previous_open &&
|
34
|
+
close > previous_open &&
|
35
|
+
close < previous_high &&
|
36
|
+
close < second_previous_close
|
37
|
+
patterns << :bearish_engulfing
|
38
|
+
|
39
|
+
elsif close > previous_close &&
|
40
|
+
previous_close < previous_open &&
|
41
|
+
close < previous_open &&
|
42
|
+
close < previous_low &&
|
43
|
+
close < second_previous_close
|
44
|
+
patterns << :bearish_harami
|
45
|
+
|
46
|
+
elsif close < previous_close &&
|
47
|
+
previous_close > previous_open &&
|
48
|
+
close > previous_open &&
|
49
|
+
close > previous_high &&
|
50
|
+
close > second_previous_close
|
51
|
+
patterns << :bullish_harami
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
patterns
|
57
|
+
end
|
58
|
+
|
59
|
+
end; end
|
60
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# lib/sqa/indicator/classify_market_profile.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def classify_market_profile(
|
6
|
+
volumes, # Array of volumes
|
7
|
+
prices, # Array of prices
|
8
|
+
support_threshold, # Float stock's support price estimate
|
9
|
+
resistance_threshold # Float stock's resistance price estimate
|
10
|
+
)
|
11
|
+
return :unknown if volumes.empty? || prices.empty?
|
12
|
+
|
13
|
+
total_volume = volumes.sum
|
14
|
+
average_volume = total_volume / volume.length.to_f
|
15
|
+
max_volume = volume.max
|
16
|
+
|
17
|
+
support_levels = prices.select { |price| price <= support_threshold }
|
18
|
+
resistance_levels = prices.select { |price| price >= resistance_threshold }
|
19
|
+
|
20
|
+
if support_levels.empty? &&
|
21
|
+
resistance_levels.empty?
|
22
|
+
:neutral
|
23
|
+
elsif support_levels.empty?
|
24
|
+
:resistance
|
25
|
+
elsif resistance_levels.empty?
|
26
|
+
:support
|
27
|
+
else
|
28
|
+
:mixed
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end; end
|
33
|
+
|
@@ -0,0 +1,5 @@
|
|
1
|
+
# Donchian Channel
|
2
|
+
|
3
|
+
In the domain of computer programming, a Donchian Channel is a technical analysis indicator used to identify potential breakouts and trend reversals in financial markets. It consists of three lines: the upper channel line, the lower channel line, and the middle line.
|
4
|
+
|
5
|
+
The upper channel line is calculated by finding the highest high over a specified period of time, while the lower channel line is calculated by finding the lowest low over the same period. The middle line is simply the average of the upper and lower channel lines.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# lib/sqa/indicator/donchian_channel.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def donchian_channel(
|
6
|
+
prices, # Array of prices
|
7
|
+
period # Integer number of entries to consider
|
8
|
+
)
|
9
|
+
max = -999999999
|
10
|
+
min = 999999999
|
11
|
+
donchian_channel = []
|
12
|
+
|
13
|
+
prices.each_with_index do |value, index|
|
14
|
+
value = value.to_f
|
15
|
+
max = value if value > max
|
16
|
+
min = value if value < min
|
17
|
+
|
18
|
+
if index >= period - 1
|
19
|
+
donchian_channel << [max, min, (max + min) / 2]
|
20
|
+
max = -999999999
|
21
|
+
min = 999999999
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
donchian_channel
|
26
|
+
end
|
27
|
+
|
28
|
+
end; end
|
29
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# lib/sqa/indicator/double_top_bottom_pattern.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def double_top_bottom_pattern(
|
6
|
+
prices # Array of prices
|
7
|
+
)
|
8
|
+
return :no_pattern if prices.length < 5
|
9
|
+
|
10
|
+
data = prices.last(5)
|
11
|
+
|
12
|
+
first_peak = data[0]
|
13
|
+
valley = data[1]
|
14
|
+
second_peak = data[2]
|
15
|
+
neckline = data[3]
|
16
|
+
confirmation_price = data[4]
|
17
|
+
|
18
|
+
if first_peak < second_peak &&
|
19
|
+
valley > first_peak &&
|
20
|
+
valley > second_peak &&
|
21
|
+
confirmation_price < neckline
|
22
|
+
:double_top
|
23
|
+
elsif first_peak > second_peak &&
|
24
|
+
valley < first_peak &&
|
25
|
+
valley < second_peak &&
|
26
|
+
confirmation_price > neckline
|
27
|
+
:double_bottom
|
28
|
+
else
|
29
|
+
:no_pattern
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end; end
|
34
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Exponential Moving Average (EMA)
|
2
|
+
|
3
|
+
In financial analysis, the Exponential Moving Average (EMA) is a commonly used technical indicator that helps identify trends and smooth out price data. It is a type of moving average that gives more weight to recent prices, making it more responsive to recent price changes compared to other moving averages.
|
4
|
+
|
5
|
+
The EMA is calculated by applying a smoothing factor (often represented as a percentage) to the previous EMA value and adding a weighted average of the current price. The smoothing factor determines the weight given to the most recent price data, with higher values giving more weight to recent prices.
|
6
|
+
|
7
|
+
The EMA is used for various purposes in financial analysis, including:
|
8
|
+
|
9
|
+
1. Trend Identification: The EMA is often used to identify the direction and strength of a trend. When the current price is above the EMA, it suggests an uptrend, while a price below the EMA suggests a downtrend. Traders and investors may use the EMA crossover (when the price crosses above or below the EMA) as a signal to enter or exit positions.
|
10
|
+
|
11
|
+
2. Support and Resistance Levels: The EMA can act as dynamic support or resistance levels. In an uptrend, the EMA may provide support, and in a downtrend, it may act as resistance. Traders may use the EMA as a reference point for setting stop-loss orders or profit targets.
|
12
|
+
|
13
|
+
3. Price Reversals: The EMA can help identify potential price reversals. When the price deviates significantly from the EMA, it may indicate an overbought or oversold condition, suggesting a potential reversal in the near future. Traders may use this information to anticipate price reversals and adjust their trading strategies accordingly.
|
14
|
+
|
15
|
+
4. Volatility Assessment: The EMA can be used to assess market volatility. When the EMA is relatively flat, it suggests low volatility, while a steeply sloping EMA indicates higher volatility. Traders may adjust their trading strategies based on the level of volatility indicated by the EMA.
|
16
|
+
|
17
|
+
It's important to note that the EMA is just one of many technical indicators used in financial analysis. It is often used in combination with other indicators, such as the Simple Moving Average (SMA), to gain a more comprehensive understanding of market trends and price movements.
|
18
|
+
|
19
|
+
Traders and investors should consider their own trading strategies, risk tolerance, and timeframes when using the EMA or any other technical indicator for financial analysis. It's also recommended to backtest and validate any trading strategies before applying them in real-time trading.
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# lib/sqa/indicator/ema_analysis.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def ema_analysis(
|
6
|
+
prices, # Array of prices
|
7
|
+
period # Integer number of entries to consider
|
8
|
+
)
|
9
|
+
return {} if prices.empty? || period <= 0
|
10
|
+
|
11
|
+
ema_values = []
|
12
|
+
ema_values << prices.first
|
13
|
+
|
14
|
+
multiplier = (2.0 / (period + 1))
|
15
|
+
|
16
|
+
(1...prices.length).each do |i|
|
17
|
+
ema = (prices[i] - ema_values.last) * multiplier + ema_values.last
|
18
|
+
ema_values << ema.round(2)
|
19
|
+
end
|
20
|
+
|
21
|
+
analysis = {}
|
22
|
+
|
23
|
+
analysis[:ema_values] = ema_values
|
24
|
+
analysis[:trend] = ema_determine_trend(ema_values)
|
25
|
+
analysis[:support] = ema_determine_support(ema_values)
|
26
|
+
analysis[:resistance] = ema_determine_resistance(ema_values)
|
27
|
+
|
28
|
+
analysis
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# @param ema_values [Array] An array of EMA values.
|
33
|
+
# @return [Symbol] The trend: :up, :down, or :sideways.
|
34
|
+
#
|
35
|
+
private def ema_determine_trend(ema_values)
|
36
|
+
return :sideways if ema_values.empty?
|
37
|
+
|
38
|
+
last_ema = ema_values.last
|
39
|
+
previous_ema = ema_values[-2]
|
40
|
+
|
41
|
+
if last_ema > previous_ema
|
42
|
+
:up
|
43
|
+
elsif last_ema < previous_ema
|
44
|
+
:down
|
45
|
+
else
|
46
|
+
:sideways
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# @param ema_values [Array] An array of EMA values.
|
52
|
+
# @return [Float] The support level.
|
53
|
+
#
|
54
|
+
private def ema_determine_support(ema_values)
|
55
|
+
return 0.0 if ema_values.empty?
|
56
|
+
|
57
|
+
ema_values.min
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# @param ema_values [Array] An array of EMA values.
|
62
|
+
# @return [Float] The resistance level.
|
63
|
+
private def ema_determine_resistance(ema_values)
|
64
|
+
return 0.0 if ema_values.empty?
|
65
|
+
|
66
|
+
ema_values.max
|
67
|
+
end
|
68
|
+
|
69
|
+
end; end
|
70
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# lib/sqa/indicator/fibonacci_retracement.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def fibonacci_retracement(
|
6
|
+
start_price, # Float starting price of the range
|
7
|
+
end_price # Float ending price of the range
|
8
|
+
)
|
9
|
+
retracement_levels = []
|
10
|
+
|
11
|
+
retracement_levels << end_price
|
12
|
+
retracement_levels << start_price
|
13
|
+
|
14
|
+
fibonacci_levels = [0.236, 0.382, 0.5, 0.618, 0.786]
|
15
|
+
|
16
|
+
fibonacci_levels.each do |level|
|
17
|
+
retracement_levels <<= start_price + (end_price - start_price) * level
|
18
|
+
end
|
19
|
+
|
20
|
+
retracement_levels # Array
|
21
|
+
end
|
22
|
+
alias_method :fr, :fibonacci_retracement
|
23
|
+
|
24
|
+
end; end
|
25
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# lib/sqa/indicator/head_and_shoulders_pattern.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
|
6
|
+
def head_and_shoulders_pattern?(
|
7
|
+
prices # Array of prices
|
8
|
+
)
|
9
|
+
|
10
|
+
return false if prices.length < 5
|
11
|
+
|
12
|
+
data = prices.last(5)
|
13
|
+
|
14
|
+
left_shoulder = data[0]
|
15
|
+
head = data[1]
|
16
|
+
right_shoulder = data[2]
|
17
|
+
neckline = data[3]
|
18
|
+
right_peak = data[4]
|
19
|
+
|
20
|
+
head > left_shoulder &&
|
21
|
+
head > right_shoulder &&
|
22
|
+
right_peak < neckline
|
23
|
+
end
|
24
|
+
|
25
|
+
end; end
|
26
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Wave Theory
|
2
|
+
|
3
|
+
Wave theory, such as Elliott Wave Theory, suggests that price movements follow repetitive patterns or waves. It aims to identify and predict these patterns to make trading decisions.
|
4
|
+
|
5
|
+
Identifies a wave condition in a stock's price history based on a given price series.
|
6
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# lib/sqa/indicator/identify_wave_condition.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
def identify_wave_condition?(
|
6
|
+
prices, # Array of prices
|
7
|
+
wave_length, # Integer expected length of a wave pattern
|
8
|
+
tolerance # Float delta change in price that would indicate a wave
|
9
|
+
)
|
10
|
+
return false if prices.length < wave_length
|
11
|
+
|
12
|
+
wave_start = 0
|
13
|
+
wave_end = wave_length - 1
|
14
|
+
|
15
|
+
while wave_end < prices.length
|
16
|
+
wave = prices[wave_start..wave_end]
|
17
|
+
|
18
|
+
if wave.length == wave_length &&
|
19
|
+
wave_pattern?(wave, tolerance)
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
|
23
|
+
wave_start += 1
|
24
|
+
wave_end += 1
|
25
|
+
end
|
26
|
+
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
private def wave_pattern?(wave, tolerance)
|
32
|
+
wave.each_cons(2) do |a, b|
|
33
|
+
return false if (b - a).abs > tolerance
|
34
|
+
end
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
end; end
|
40
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Mean Reversion
|
2
|
+
|
3
|
+
Determines if a stock exhibits mean reversion behavior based on a given price series.
|
4
|
+
|
5
|
+
Mean Reversion Strategies: Mean reversion strategies aim to capitalize on the tendency of prices to revert to their mean or average value. These strategies involve identifying overextended price movements and taking positions that anticipate a return to the mean.
|
6
|
+
|
7
|
+
|
8
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# lib/sqa/indicator/mean_reversion.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
# @param prices [Array]
|
6
|
+
# @param lookback_period [Integer]
|
7
|
+
# @param deviation_threshold [Float]
|
8
|
+
#
|
9
|
+
# @return [Boolean] True if the stock exhibits mean reversion behavior,
|
10
|
+
# false otherwise.
|
11
|
+
#
|
12
|
+
def mean_reversion?(
|
13
|
+
prices, # Array of prices
|
14
|
+
lookback_period, # Integer number of events to consider
|
15
|
+
deviation_threshold # Float delta change at which a price is considered to be over extended
|
16
|
+
)
|
17
|
+
|
18
|
+
return false if prices.length < lookback_period
|
19
|
+
|
20
|
+
mean = mr_mean(prices, lookback_period)
|
21
|
+
deviation = prices[-1] - mean
|
22
|
+
|
23
|
+
if deviation.abs > deviation_threshold
|
24
|
+
return true
|
25
|
+
else
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def mr_mean(prices, lookback_period)
|
32
|
+
prices.last(lookback_period).sum / lookback_period.to_f
|
33
|
+
end
|
34
|
+
|
35
|
+
end; end
|
36
|
+
|
37
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Momentum
|
2
|
+
|
3
|
+
Calculates the momentum of a stock based on the rate of change (ROC).
|
4
|
+
|
5
|
+
The interpretation of a stock's momentum value in terms of forecasting future price depends on the specific trading strategy or approach being used. However, in general, a positive momentum value indicates that the stock's price has been increasing over the specified period, while a negative momentum value indicates that the stock's price has been decreasing.
|
6
|
+
|
7
|
+
Here are some common interpretations of momentum values:
|
8
|
+
|
9
|
+
1. Positive Momentum: A positive momentum value suggests that the stock's price has been trending upwards. This could indicate that the stock is in an uptrend and may continue to rise in the near future. Traders and investors may interpret this as a bullish signal and consider buying or holding the stock.
|
10
|
+
|
11
|
+
2. Negative Momentum: A negative momentum value suggests that the stock's price has been trending downwards. This could indicate that the stock is in a downtrend and may continue to decline in the near future. Traders and investors may interpret this as a bearish signal and consider selling or avoiding the stock.
|
12
|
+
|
13
|
+
3. High Momentum: A high positive momentum value indicates a strong upward trend in the stock's price. This could suggest that the stock has significant buying pressure and may continue to rise. Traders and investors may interpret this as a strong bullish signal and consider entering or adding to their positions.
|
14
|
+
|
15
|
+
4. Low Momentum: A low positive momentum value suggests a weak upward trend or a sideways movement in the stock's price. This could indicate a lack of significant buying pressure. Traders and investors may interpret this as a neutral signal and may choose to wait for a stronger momentum signal or look for other indicators to make trading decisions.
|
16
|
+
|
17
|
+
It's important to note that momentum alone may not be sufficient for accurate price forecasting. It is often used in conjunction with other technical indicators, fundamental analysis, or market conditions to make more informed trading decisions.
|
18
|
+
|
19
|
+
Additionally, the interpretation of momentum values may vary depending on the time frame and the specific trading strategy being employed. Traders and investors should consider their own risk tolerance, investment goals, and trading approach when interpreting momentum values for forecasting future price movements.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# lib/sqa/indicator/momentum.rb
|
2
|
+
|
3
|
+
module SQA::Indicator; class << self
|
4
|
+
|
5
|
+
# @param prices [Array]
|
6
|
+
# @param period [Integer]
|
7
|
+
#
|
8
|
+
# @return [Float]
|
9
|
+
#
|
10
|
+
def momentum(
|
11
|
+
prices, # Array of prices
|
12
|
+
period # Integer number of entries to consider
|
13
|
+
)
|
14
|
+
return 0.0 if prices.length <= period
|
15
|
+
|
16
|
+
current_price = prices.last
|
17
|
+
past_price = prices.last(period).first
|
18
|
+
change = (current_price - past_price) / past_price.to_f
|
19
|
+
momentum = change * 100.0
|
20
|
+
|
21
|
+
momentum # Float expressed as a percentage change
|
22
|
+
end
|
23
|
+
alias_method :m, :momentum
|
24
|
+
|
25
|
+
end; end
|
26
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Moving Average Convergence Divergence (MACD)
|
2
|
+
|
3
|
+
The MACD is a trend-following momentum indicator that measures the relationship between two moving averages over a specified time period. The MACD is calculated by subtracting the long-term moving average from the short-term moving average.
|
4
|
+
|
5
|
+
The method takes in an array of historical prices for a stock, a short period (the number of days to calculate the short-term moving average over), a long period (the number of days to calculate the long-term moving average over), and a signal period (the number of days to calculate the signal line moving average over).
|
6
|
+
|
7
|
+
The method first calculates the short-term moving average by calling the `moving_averages` method with the `prices` array and the `short_period` parameter. It then calculates the long-term moving average by calling the `moving_averages` method with the `prices` array and the `long_period` parameter.
|
8
|
+
|
9
|
+
Next, the method calculates the MACD line by subtracting the long-term moving average from the short-term moving average. This is done by taking the last element of the `short_ma` array (which contains the short-term moving averages for each window) and subtracting the last element of the `long_ma` array (which contains the long-term moving averages for each window).
|
10
|
+
|
11
|
+
Finally, the method calculates the signal line by taking the moving average of the MACD line over the specified `signal_period`. This is done by calling the `moving_averages` method with the `short_ma` array and the `signal_period` parameter, and taking the last element of the resulting array.
|
12
|
+
|
13
|
+
The method returns an array containing the MACD line and the signal line.
|
14
|
+
|
15
|
+
Note that this is just a basic implementation of the MACD indicator, and there are many variations and refinements that can be made depending on the specific requirements of your program.
|
16
|
+
|
17
|
+
The Moving Average Convergence Divergence (MACD) is a technical analysis indicator that is used to identify changes in momentum, direction, and trend for a security. The MACD is calculated by subtracting the 26-period exponential moving average (EMA) from the 12-period EMA.
|
18
|
+
|
19
|
+
The values 1.8231937142857078 and 164.44427957142855 that you provided are likely the MACD line and the signal line, respectively. The MACD line is the difference between the 12-period EMA and the 26-period EMA, while the signal line is a 9-period EMA of the MACD line.
|
20
|
+
|
21
|
+
The MACD line crossing above the signal line is often considered a bullish signal, while the MACD line crossing below the signal line is often considered a bearish signal. The distance between the MACD line and the signal line can also provide insight into the strength of the trend.
|
22
|
+
|
23
|
+
Without additional context, it's difficult to interpret the specific values of 1.8231937142857078 and 164.44427957142855 for the MACD and signal lines of a stock. However, in general, the MACD can be used to identify potential buy and sell signals for a security, as well as to provide insight into the strength of the trend.
|