td-sequential 1.0.0__tar.gz
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.
- td_sequential-1.0.0/.gitignore +5 -0
- td_sequential-1.0.0/CHANGELOG.md +7 -0
- td_sequential-1.0.0/LICENSE +21 -0
- td_sequential-1.0.0/PKG-INFO +145 -0
- td_sequential-1.0.0/README.md +111 -0
- td_sequential-1.0.0/SPEC.md +198 -0
- td_sequential-1.0.0/pyproject.toml +54 -0
- td_sequential-1.0.0/src/td_sequential/__init__.py +6 -0
- td_sequential-1.0.0/src/td_sequential/core.py +260 -0
- td_sequential-1.0.0/src/td_sequential/pandas.py +50 -0
- td_sequential-1.0.0/src/td_sequential/py.typed +0 -0
- td_sequential-1.0.0/tests/fixtures/BNBUSDT-binance-1w.json +1 -0
- td_sequential-1.0.0/tests/fixtures/BTCUSDT-binance-1d.json +1 -0
- td_sequential-1.0.0/tests/fixtures/DOGEUSDT-binance-1w.json +1 -0
- td_sequential-1.0.0/tests/fixtures/ETHUSDT-binance-1w.json +1 -0
- td_sequential-1.0.0/tests/fixtures/LINKUSDT-binance-4h.json +1 -0
- td_sequential-1.0.0/tests/fixtures/LTCUSDT-binance-4h.json +1 -0
- td_sequential-1.0.0/tests/fixtures/SOLUSDT-binance-4h.json +1 -0
- td_sequential-1.0.0/tests/fixtures/XRPUSDT-binance-1d.json +1 -0
- td_sequential-1.0.0/tests/test_pandas.py +37 -0
- td_sequential-1.0.0/tests/test_parity.py +89 -0
- td_sequential-1.0.0/tests/test_td_sequential.py +239 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0 - 2026-10-28
|
|
4
|
+
|
|
5
|
+
- First release: TD Setup, TD Countdown, TDST support and resistance levels, 13-versus-8 deferral, and the information-only perfection and price flip flags.
|
|
6
|
+
- `compute(bars)` and `latest(result)`; optional `td_sequential.pandas.add_td_sequential(df)`.
|
|
7
|
+
- Verified bar for bar against shared reference fixtures.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Moolish
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: td-sequential
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: TD Sequential indicator for Python: TD9 setup, countdown 13 and TDST levels on OHLC candles. Tested, zero dependencies.
|
|
5
|
+
Project-URL: Homepage, https://moolish.com/tools/td-sequential-counter/
|
|
6
|
+
Project-URL: Documentation, https://moolish.com/learn/td-sequential/
|
|
7
|
+
Project-URL: Source, https://github.com/moolish-com/td-sequential-python
|
|
8
|
+
Project-URL: Issues, https://github.com/moolish-com/td-sequential-python/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/moolish-com/td-sequential-python/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Moolish <support@moolish.com>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: crypto,forex,indicator,ohlc,pandas,stocks,td-countdown,td-sequential,td-setup,td9,tdsequential,tdst,technical-analysis,tom-demark,trading
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.9
|
|
28
|
+
Provides-Extra: pandas
|
|
29
|
+
Requires-Dist: pandas>=1.5; extra == 'pandas'
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: pandas>=1.5; extra == 'test'
|
|
32
|
+
Requires-Dist: pytest>=7; extra == 'test'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# TD Sequential indicator for Python
|
|
36
|
+
|
|
37
|
+
[](https://github.com/moolish-com/td-sequential-python/actions/workflows/test.yml)
|
|
38
|
+
[](https://pypi.org/project/td-sequential/)
|
|
39
|
+
[](https://pypi.org/project/td-sequential/)
|
|
40
|
+
[](https://pypi.org/project/td-sequential/)
|
|
41
|
+
[](LICENSE)
|
|
42
|
+
|
|
43
|
+
`td-sequential` computes the TD Sequential indicator in Python on a list of OHLC candles: the TD Setup (the 1 to 9 count, often called TD9), the TD Countdown (1 to 13), the TDST support and resistance levels left by completed setups, and the information-only perfection and price flip flags. It works on crypto, stocks and forex candles of any timeframe, has no dependencies, supports Python 3.9 and later, and has an optional pandas helper.
|
|
44
|
+
|
|
45
|
+
It follows the plain-English rules in [SPEC.md](SPEC.md) and matches the reference output bar for bar. The free [TD Sequential counter](https://moolish.com/tools/td-sequential-counter/) on moolish.com shows the current count on a crypto pair without installing anything.
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install td-sequential
|
|
51
|
+
pip install "td-sequential[pandas]" # optional DataFrame helper
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from td_sequential import compute, latest
|
|
58
|
+
|
|
59
|
+
# Closed bars only, oldest first. Drop the candle that is still forming.
|
|
60
|
+
bars = [
|
|
61
|
+
{"t": 1750032000000, "o": 105594.02, "h": 108952.38, "l": 104980.37, "c": 106794.53},
|
|
62
|
+
# ...
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
result = compute(bars) # one TdBar record per input bar
|
|
66
|
+
now = latest(result) # summary of the last bar
|
|
67
|
+
|
|
68
|
+
last = result[-1]
|
|
69
|
+
if last.buy_setup == 9:
|
|
70
|
+
print("TD Setup 9 (buy) on", last.t, "resistance", last.resistance)
|
|
71
|
+
if last.sell_countdown == 13:
|
|
72
|
+
print("TD Countdown 13 (sell) completed on", last.t)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
A bar can be a dict with keys `t, o, h, l, c` (the long names `time, open, high, low, close` also work), a `(t, o, h, l, c)` tuple, or any object with those attributes, for example a named tuple or a dataclass. Missing fields and non-numeric prices raise a clear `ValueError` or `TypeError` that names the bar.
|
|
76
|
+
|
|
77
|
+
### pandas
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import pandas as pd
|
|
81
|
+
from td_sequential.pandas import add_td_sequential
|
|
82
|
+
|
|
83
|
+
df = pd.read_csv("btcusdt-1d.csv", index_col="time", parse_dates=True) # open, high, low, close columns
|
|
84
|
+
out = add_td_sequential(df) # returns a copy with td_* columns added
|
|
85
|
+
print(out[out["td_buy_setup"] == 9])
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Column names are case-insensitive on input. Output columns carry the prefix `td_` (change it with `prefix=`). `td_resistance` and `td_support` are `NaN` when there is no active level.
|
|
89
|
+
|
|
90
|
+
## Output fields
|
|
91
|
+
|
|
92
|
+
`compute()` returns a list of frozen `TdBar` dataclasses, one per input bar, in input order.
|
|
93
|
+
|
|
94
|
+
| Field | Type | Meaning |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `t` | any | The bar's timestamp, copied from the input |
|
|
97
|
+
| `buy_setup` | int | Buy TD Setup counter (0 or more; exactly 9 marks a setup 9) |
|
|
98
|
+
| `sell_setup` | int | Sell TD Setup counter, same meaning |
|
|
99
|
+
| `buy_countdown` | int | Signed buy countdown; 13 means just completed; 14 or more means no countdown in progress; negative means paused |
|
|
100
|
+
| `sell_countdown` | int | Signed sell countdown, same meaning |
|
|
101
|
+
| `resistance` | float or None | Price of the active latest TDST resistance level (plain highest high of the 9 setup bars) |
|
|
102
|
+
| `support` | float or None | Price of the active latest TDST support level (plain lowest low of the 9 setup bars) |
|
|
103
|
+
| `buy_deferred` | bool | The 13th buy countdown bar was held back by the 13-versus-8 test |
|
|
104
|
+
| `sell_deferred` | bool | Same for the sell countdown |
|
|
105
|
+
| `buy_perfected` | bool | Buy setup 9 whose bar 8 or 9 low is strictly below the lows of bars 6 and 7 (information only) |
|
|
106
|
+
| `sell_perfected` | bool | Sell setup 9 whose bar 8 or 9 high is strictly above the highs of bars 6 and 7 (information only) |
|
|
107
|
+
| `bullish_flip` | bool | Price flip: close crosses above the close 4 bars earlier after being below it (information only) |
|
|
108
|
+
| `bearish_flip` | bool | The mirror price flip (information only) |
|
|
109
|
+
|
|
110
|
+
The four information-only fields never change a setup, countdown or level value.
|
|
111
|
+
|
|
112
|
+
`latest(result)` returns a `Latest` dataclass: the current setup counts, the countdown in progress per side (`CountdownState(count, paused)` or `None`), whether a 13 just completed, the time of the last completed setup 9 and countdown 13 per side, and the active resistance and support. It returns `None` for an empty result.
|
|
113
|
+
|
|
114
|
+
## Rules in short
|
|
115
|
+
|
|
116
|
+
- Setup: a bar counts when its close is lower (buy) or higher (sell) than the close 4 bars earlier. Any bar that does not qualify resets the counter to 0. Counting does not stop at 9.
|
|
117
|
+
- Levels: a buy setup 9 records the highest high of its 9 bars as resistance, a sell setup 9 the lowest low as support (the "TDST levels", using the plain 9-bar high and low). A level is dropped when price closes beyond it or a whole bar sits beyond it.
|
|
118
|
+
- Countdown: starts on the setup 9 bar; a bar counts when its close is at or beyond the low (buy) or high (sell) of the bar 2 bars earlier. It needs an active level, is cancelled by the opposite setup 9, and the 13th bar must pass the 13-versus-8 test.
|
|
119
|
+
|
|
120
|
+
The full, unambiguous version is in [SPEC.md](SPEC.md).
|
|
121
|
+
|
|
122
|
+
## Verified against reference data
|
|
123
|
+
|
|
124
|
+
The test suite replays eight real candle histories (crypto pairs on 4-hour, daily and weekly timeframes, about 500 bars each) and requires every counting field to match the stored reference output on every bar. It also compares all twelve fields with the JavaScript implementation of the same rules on the same bars, and has unit cases for setup, levels, countdown, the 13-versus-8 deferral, perfection and price flips. Run it with `pip install -e ".[test]"` then `pytest`.
|
|
125
|
+
|
|
126
|
+
## What is TD Sequential?
|
|
127
|
+
|
|
128
|
+
TD Sequential is Tom DeMark's method for spotting a stretched run of closes. A TD Setup counts consecutive bars that close beyond the close four bars earlier, and a completed 9 can start a countdown that needs 13 qualifying bars. A 9 or a 13 describes past prices and gives no direction on its own; the [TD Sequential guide](https://moolish.com/learn/td-sequential/) explains the method, [TDST](https://moolish.com/learn/td-sequential/tdst/) and [perfected setups](https://moolish.com/learn/td-sequential/perfected-setup/).
|
|
129
|
+
|
|
130
|
+
## Related
|
|
131
|
+
|
|
132
|
+
- [td-sequential](https://github.com/moolish-com/td-sequential) - JavaScript and TypeScript (npm)
|
|
133
|
+
- [td-sequential-pine-script](https://github.com/moolish-com/td-sequential-pine-script) - TradingView Pine Script v6
|
|
134
|
+
- [td-sequential-screener](https://github.com/moolish-com/td-sequential-screener) - command-line screener
|
|
135
|
+
- [Free TD Sequential counter](https://moolish.com/tools/td-sequential-counter/) - check a crypto pair in the browser
|
|
136
|
+
|
|
137
|
+
## Attribution and disclaimer
|
|
138
|
+
|
|
139
|
+
Moolish is not affiliated with, endorsed by or sponsored by Tom DeMark or DeMARK Analytics. TD Sequential is a method created by Tom DeMark, and DeMARK is a trademark of DeMARK Analytics.
|
|
140
|
+
|
|
141
|
+
This is educational software, not financial advice. A count describes past prices; it is not a prediction.
|
|
142
|
+
|
|
143
|
+
## Licence
|
|
144
|
+
|
|
145
|
+
[MIT](LICENSE) - Copyright (c) 2026 Moolish
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# TD Sequential indicator for Python
|
|
2
|
+
|
|
3
|
+
[](https://github.com/moolish-com/td-sequential-python/actions/workflows/test.yml)
|
|
4
|
+
[](https://pypi.org/project/td-sequential/)
|
|
5
|
+
[](https://pypi.org/project/td-sequential/)
|
|
6
|
+
[](https://pypi.org/project/td-sequential/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
`td-sequential` computes the TD Sequential indicator in Python on a list of OHLC candles: the TD Setup (the 1 to 9 count, often called TD9), the TD Countdown (1 to 13), the TDST support and resistance levels left by completed setups, and the information-only perfection and price flip flags. It works on crypto, stocks and forex candles of any timeframe, has no dependencies, supports Python 3.9 and later, and has an optional pandas helper.
|
|
10
|
+
|
|
11
|
+
It follows the plain-English rules in [SPEC.md](SPEC.md) and matches the reference output bar for bar. The free [TD Sequential counter](https://moolish.com/tools/td-sequential-counter/) on moolish.com shows the current count on a crypto pair without installing anything.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install td-sequential
|
|
17
|
+
pip install "td-sequential[pandas]" # optional DataFrame helper
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from td_sequential import compute, latest
|
|
24
|
+
|
|
25
|
+
# Closed bars only, oldest first. Drop the candle that is still forming.
|
|
26
|
+
bars = [
|
|
27
|
+
{"t": 1750032000000, "o": 105594.02, "h": 108952.38, "l": 104980.37, "c": 106794.53},
|
|
28
|
+
# ...
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
result = compute(bars) # one TdBar record per input bar
|
|
32
|
+
now = latest(result) # summary of the last bar
|
|
33
|
+
|
|
34
|
+
last = result[-1]
|
|
35
|
+
if last.buy_setup == 9:
|
|
36
|
+
print("TD Setup 9 (buy) on", last.t, "resistance", last.resistance)
|
|
37
|
+
if last.sell_countdown == 13:
|
|
38
|
+
print("TD Countdown 13 (sell) completed on", last.t)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
A bar can be a dict with keys `t, o, h, l, c` (the long names `time, open, high, low, close` also work), a `(t, o, h, l, c)` tuple, or any object with those attributes, for example a named tuple or a dataclass. Missing fields and non-numeric prices raise a clear `ValueError` or `TypeError` that names the bar.
|
|
42
|
+
|
|
43
|
+
### pandas
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import pandas as pd
|
|
47
|
+
from td_sequential.pandas import add_td_sequential
|
|
48
|
+
|
|
49
|
+
df = pd.read_csv("btcusdt-1d.csv", index_col="time", parse_dates=True) # open, high, low, close columns
|
|
50
|
+
out = add_td_sequential(df) # returns a copy with td_* columns added
|
|
51
|
+
print(out[out["td_buy_setup"] == 9])
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Column names are case-insensitive on input. Output columns carry the prefix `td_` (change it with `prefix=`). `td_resistance` and `td_support` are `NaN` when there is no active level.
|
|
55
|
+
|
|
56
|
+
## Output fields
|
|
57
|
+
|
|
58
|
+
`compute()` returns a list of frozen `TdBar` dataclasses, one per input bar, in input order.
|
|
59
|
+
|
|
60
|
+
| Field | Type | Meaning |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `t` | any | The bar's timestamp, copied from the input |
|
|
63
|
+
| `buy_setup` | int | Buy TD Setup counter (0 or more; exactly 9 marks a setup 9) |
|
|
64
|
+
| `sell_setup` | int | Sell TD Setup counter, same meaning |
|
|
65
|
+
| `buy_countdown` | int | Signed buy countdown; 13 means just completed; 14 or more means no countdown in progress; negative means paused |
|
|
66
|
+
| `sell_countdown` | int | Signed sell countdown, same meaning |
|
|
67
|
+
| `resistance` | float or None | Price of the active latest TDST resistance level (plain highest high of the 9 setup bars) |
|
|
68
|
+
| `support` | float or None | Price of the active latest TDST support level (plain lowest low of the 9 setup bars) |
|
|
69
|
+
| `buy_deferred` | bool | The 13th buy countdown bar was held back by the 13-versus-8 test |
|
|
70
|
+
| `sell_deferred` | bool | Same for the sell countdown |
|
|
71
|
+
| `buy_perfected` | bool | Buy setup 9 whose bar 8 or 9 low is strictly below the lows of bars 6 and 7 (information only) |
|
|
72
|
+
| `sell_perfected` | bool | Sell setup 9 whose bar 8 or 9 high is strictly above the highs of bars 6 and 7 (information only) |
|
|
73
|
+
| `bullish_flip` | bool | Price flip: close crosses above the close 4 bars earlier after being below it (information only) |
|
|
74
|
+
| `bearish_flip` | bool | The mirror price flip (information only) |
|
|
75
|
+
|
|
76
|
+
The four information-only fields never change a setup, countdown or level value.
|
|
77
|
+
|
|
78
|
+
`latest(result)` returns a `Latest` dataclass: the current setup counts, the countdown in progress per side (`CountdownState(count, paused)` or `None`), whether a 13 just completed, the time of the last completed setup 9 and countdown 13 per side, and the active resistance and support. It returns `None` for an empty result.
|
|
79
|
+
|
|
80
|
+
## Rules in short
|
|
81
|
+
|
|
82
|
+
- Setup: a bar counts when its close is lower (buy) or higher (sell) than the close 4 bars earlier. Any bar that does not qualify resets the counter to 0. Counting does not stop at 9.
|
|
83
|
+
- Levels: a buy setup 9 records the highest high of its 9 bars as resistance, a sell setup 9 the lowest low as support (the "TDST levels", using the plain 9-bar high and low). A level is dropped when price closes beyond it or a whole bar sits beyond it.
|
|
84
|
+
- Countdown: starts on the setup 9 bar; a bar counts when its close is at or beyond the low (buy) or high (sell) of the bar 2 bars earlier. It needs an active level, is cancelled by the opposite setup 9, and the 13th bar must pass the 13-versus-8 test.
|
|
85
|
+
|
|
86
|
+
The full, unambiguous version is in [SPEC.md](SPEC.md).
|
|
87
|
+
|
|
88
|
+
## Verified against reference data
|
|
89
|
+
|
|
90
|
+
The test suite replays eight real candle histories (crypto pairs on 4-hour, daily and weekly timeframes, about 500 bars each) and requires every counting field to match the stored reference output on every bar. It also compares all twelve fields with the JavaScript implementation of the same rules on the same bars, and has unit cases for setup, levels, countdown, the 13-versus-8 deferral, perfection and price flips. Run it with `pip install -e ".[test]"` then `pytest`.
|
|
91
|
+
|
|
92
|
+
## What is TD Sequential?
|
|
93
|
+
|
|
94
|
+
TD Sequential is Tom DeMark's method for spotting a stretched run of closes. A TD Setup counts consecutive bars that close beyond the close four bars earlier, and a completed 9 can start a countdown that needs 13 qualifying bars. A 9 or a 13 describes past prices and gives no direction on its own; the [TD Sequential guide](https://moolish.com/learn/td-sequential/) explains the method, [TDST](https://moolish.com/learn/td-sequential/tdst/) and [perfected setups](https://moolish.com/learn/td-sequential/perfected-setup/).
|
|
95
|
+
|
|
96
|
+
## Related
|
|
97
|
+
|
|
98
|
+
- [td-sequential](https://github.com/moolish-com/td-sequential) - JavaScript and TypeScript (npm)
|
|
99
|
+
- [td-sequential-pine-script](https://github.com/moolish-com/td-sequential-pine-script) - TradingView Pine Script v6
|
|
100
|
+
- [td-sequential-screener](https://github.com/moolish-com/td-sequential-screener) - command-line screener
|
|
101
|
+
- [Free TD Sequential counter](https://moolish.com/tools/td-sequential-counter/) - check a crypto pair in the browser
|
|
102
|
+
|
|
103
|
+
## Attribution and disclaimer
|
|
104
|
+
|
|
105
|
+
Moolish is not affiliated with, endorsed by or sponsored by Tom DeMark or DeMARK Analytics. TD Sequential is a method created by Tom DeMark, and DeMARK is a trademark of DeMARK Analytics.
|
|
106
|
+
|
|
107
|
+
This is educational software, not financial advice. A count describes past prices; it is not a prediction.
|
|
108
|
+
|
|
109
|
+
## Licence
|
|
110
|
+
|
|
111
|
+
[MIT](LICENSE) - Copyright (c) 2026 Moolish
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# TD Sequential counting rules (plain-English spec)
|
|
2
|
+
|
|
3
|
+
This document describes, in words, how to count the two TD Sequential phases
|
|
4
|
+
(Setup and Countdown) and the two price levels that go with them. It is detailed
|
|
5
|
+
enough to implement without seeing any other source, and an implementation that
|
|
6
|
+
follows it matches the reference output bar for bar on the shared test cases.
|
|
7
|
+
|
|
8
|
+
TD Sequential is a method published by Tom DeMark. This is an independent
|
|
9
|
+
description of one concrete, fully specified variant of it, not DeMark's text.
|
|
10
|
+
|
|
11
|
+
Not included: TD Combo, risk levels, and the "true high / true low"
|
|
12
|
+
variants of the support and resistance levels. Nothing here is trading advice.
|
|
13
|
+
|
|
14
|
+
## Input
|
|
15
|
+
|
|
16
|
+
- An ordered list of bars, oldest first, each with open, high, low, close and a
|
|
17
|
+
timestamp. Only closed bars are used. If the last bar is still forming, drop it
|
|
18
|
+
before counting.
|
|
19
|
+
- Bars are consecutive on the chosen timeframe. Gaps are not filled and are not
|
|
20
|
+
special: the rules look at "previous bar", "4 bars earlier" and "2 bars earlier"
|
|
21
|
+
in list order.
|
|
22
|
+
- Counting starts from the first bar of the list with empty history. Everything
|
|
23
|
+
below is evaluated once per bar, in list order, and the bar's result depends
|
|
24
|
+
only on that bar and the state left by earlier bars.
|
|
25
|
+
- Open prices and volume are never used.
|
|
26
|
+
|
|
27
|
+
## 1. Setup
|
|
28
|
+
|
|
29
|
+
Two independent counters run side by side: a buy setup and a sell setup.
|
|
30
|
+
|
|
31
|
+
For each bar, compare its close with the close of the bar 4 bars earlier
|
|
32
|
+
(the bar whose position is current minus 4).
|
|
33
|
+
|
|
34
|
+
- Buy setup: the bar qualifies if close is strictly lower than that close.
|
|
35
|
+
- Sell setup: the bar qualifies if close is strictly higher than that close.
|
|
36
|
+
- If the list has fewer than 4 earlier bars, the bar does not qualify.
|
|
37
|
+
- A bar with equal closes qualifies for neither counter.
|
|
38
|
+
|
|
39
|
+
Counter update for each side:
|
|
40
|
+
|
|
41
|
+
- If the bar qualifies, the counter becomes previous value plus 1.
|
|
42
|
+
- If it does not qualify, the counter becomes 0.
|
|
43
|
+
- No price flip is needed to start a count: a counter simply starts at 1 on the
|
|
44
|
+
first qualifying bar after a reset.
|
|
45
|
+
|
|
46
|
+
What happens after 9 (this is the standard configuration; the optional
|
|
47
|
+
"continuation" mode is off):
|
|
48
|
+
|
|
49
|
+
- The counter is not capped and does not restart. If the run continues the next
|
|
50
|
+
values are 10, 11, 12, and so on, until a bar fails to qualify and the counter
|
|
51
|
+
drops to 0.
|
|
52
|
+
- A "setup 9" is the bar on which the counter equals exactly 9. It happens once
|
|
53
|
+
per run. Values of 10 and above are not a new setup 9.
|
|
54
|
+
- (If continuation mode were on, the bar after 9 would restart at 1 instead of
|
|
55
|
+
10. It is not part of this spec; implementations use the behaviour above.)
|
|
56
|
+
|
|
57
|
+
Because the two comparisons are opposite, at most one of the two counters is
|
|
58
|
+
non-zero on a bar.
|
|
59
|
+
|
|
60
|
+
The earliest possible setup 9 is the 13th bar of the list (4 bars of history,
|
|
61
|
+
then 9 qualifying bars).
|
|
62
|
+
|
|
63
|
+
## 2. Support and resistance levels
|
|
64
|
+
|
|
65
|
+
Levels are created by a completed setup 9 and are tracked until price breaks
|
|
66
|
+
them. Buy and sell levels are kept in two separate lists.
|
|
67
|
+
|
|
68
|
+
Creation, evaluated on every bar before anything else that uses levels:
|
|
69
|
+
|
|
70
|
+
- On a buy setup 9: add a resistance level at the highest high of the latest 9
|
|
71
|
+
bars, including the current bar.
|
|
72
|
+
- On a sell setup 9: add a support level at the lowest low of the latest 9 bars,
|
|
73
|
+
including the current bar.
|
|
74
|
+
- A level is not added if its price is not above zero, or if a still-active
|
|
75
|
+
level in the same list already has exactly the same price.
|
|
76
|
+
- A new level becomes the "latest" level of its list, and any previous level
|
|
77
|
+
stops being the latest one.
|
|
78
|
+
- Each list keeps at most 20 levels. When a 21st is added, the oldest is dropped.
|
|
79
|
+
|
|
80
|
+
Breaking, evaluated on every bar right after creation, for every active level:
|
|
81
|
+
|
|
82
|
+
- A resistance level is broken when the bar's close is above the price, or the
|
|
83
|
+
bar's low is above the price (the whole bar sits above it).
|
|
84
|
+
- A support level is broken when the bar's close is below the price, or the
|
|
85
|
+
bar's high is below the price (the whole bar sits below it).
|
|
86
|
+
- A broken level becomes inactive for good. A level touched without being broken
|
|
87
|
+
(price pokes through and closes back) stays active; touches are counted by the
|
|
88
|
+
reference but do not change any output described here, so they are not part of
|
|
89
|
+
the contract.
|
|
90
|
+
|
|
91
|
+
Active level reported per bar:
|
|
92
|
+
|
|
93
|
+
- Resistance: the price of the latest resistance level if it is still active,
|
|
94
|
+
otherwise null.
|
|
95
|
+
- Support: the price of the latest support level if it is still active,
|
|
96
|
+
otherwise null.
|
|
97
|
+
- Only the latest level is reported. If the latest level has been broken, the
|
|
98
|
+
value is null even when an older level in the list is still active.
|
|
99
|
+
- Before any setup 9 has completed, both are null.
|
|
100
|
+
|
|
101
|
+
## 3. Countdown
|
|
102
|
+
|
|
103
|
+
Two countdowns run side by side. The buy countdown belongs to buy setup 9 and
|
|
104
|
+
needs an active resistance level. The sell countdown belongs to sell setup 9 and
|
|
105
|
+
needs an active support level.
|
|
106
|
+
|
|
107
|
+
Each countdown holds a signed integer, starting at 0. Its absolute value is the
|
|
108
|
+
number of qualifying bars counted so far. A negative sign means "this bar did
|
|
109
|
+
not qualify, the count is paused at that value". Zero has no sign.
|
|
110
|
+
|
|
111
|
+
Qualifying bar:
|
|
112
|
+
|
|
113
|
+
- Buy countdown: the bar's close is lower than or equal to the low of the bar 2
|
|
114
|
+
bars earlier.
|
|
115
|
+
- Sell countdown: the bar's close is higher than or equal to the high of the bar
|
|
116
|
+
2 bars earlier.
|
|
117
|
+
- With fewer than 2 earlier bars, a bar does not qualify.
|
|
118
|
+
- Qualifying bars need not be consecutive. They are not required to be below the
|
|
119
|
+
previous close or to follow any particular pattern; just this one comparison.
|
|
120
|
+
|
|
121
|
+
Per-bar update, for one countdown (own = its own setup, other = the opposite
|
|
122
|
+
setup). Check the cases in this order and stop at the first that applies:
|
|
123
|
+
|
|
124
|
+
1. Own setup 9 completes on this bar: the value becomes 1 if the bar qualifies,
|
|
125
|
+
otherwise 0. This starts the countdown on the setup-9 bar itself, and also
|
|
126
|
+
restarts any countdown that was already running.
|
|
127
|
+
2. Otherwise, if the opposite setup completes its 9 on this bar, or the level this
|
|
128
|
+
countdown needs (resistance for buy, support for sell) is not active: the value
|
|
129
|
+
becomes 14. This is the cancellation state.
|
|
130
|
+
3. Otherwise, if the previous value has absolute value 12 and the bar qualifies and
|
|
131
|
+
the 13-versus-8 test fails (see below): the value becomes -12 and the bar is
|
|
132
|
+
flagged as deferred.
|
|
133
|
+
4. Otherwise, if the bar qualifies: the value becomes the absolute value of the
|
|
134
|
+
previous value plus 1.
|
|
135
|
+
5. Otherwise: the value becomes the negative of the absolute value of the previous
|
|
136
|
+
value (zero stays zero).
|
|
137
|
+
|
|
138
|
+
13-versus-8 test (only used when the previous absolute value is 12):
|
|
139
|
+
|
|
140
|
+
- The close of the bar on which the countdown reached exactly 8 is remembered.
|
|
141
|
+
(Only a transition to a positive 8 counts; the remembered close is overwritten
|
|
142
|
+
each time a countdown reaches 8.)
|
|
143
|
+
- Buy countdown: the 13th qualifying bar is accepted only if its low is lower
|
|
144
|
+
than or equal to that remembered close. If its low is higher, the bar is
|
|
145
|
+
deferred.
|
|
146
|
+
- Sell countdown: accepted only if its high is higher than or equal to that
|
|
147
|
+
remembered close. If its high is lower, the bar is deferred.
|
|
148
|
+
- A deferred bar leaves the value at -12 (rule 3). The following bars repeat the
|
|
149
|
+
same test, so the countdown completes on the first later qualifying bar that
|
|
150
|
+
passes the test. While waiting, non-qualifying bars also keep -12.
|
|
151
|
+
|
|
152
|
+
Completion and what the numbers mean:
|
|
153
|
+
|
|
154
|
+
- A value of exactly 13 means the countdown has just completed on this bar. It
|
|
155
|
+
is the only way a 13 appears.
|
|
156
|
+
- The rules do not stop at 13. If the level is still active and no opposite 9
|
|
157
|
+
occurs, the next qualifying bar produces 14, then 15, and so on, with negative
|
|
158
|
+
values on non-qualifying bars. Treat any absolute value of 14 or more as "no
|
|
159
|
+
countdown in progress": it is the cancellation state, or an already finished
|
|
160
|
+
countdown, and it carries no further meaning.
|
|
161
|
+
- Cancellation (rule 2) therefore comes from two causes: the opposite setup 9, or
|
|
162
|
+
loss of the needed level (it was broken, or no level was ever created). The
|
|
163
|
+
value stays at 14 as long as the level is missing, which is why every bar of a
|
|
164
|
+
fresh list shows 14 until a setup 9 and its level exist.
|
|
165
|
+
- A new own setup 9 (rule 1) always overrides a cancelled or finished state and
|
|
166
|
+
restarts the countdown.
|
|
167
|
+
|
|
168
|
+
## 4. Output contract
|
|
169
|
+
|
|
170
|
+
One record per input bar, in input order:
|
|
171
|
+
|
|
172
|
+
| field | type | meaning |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| t | integer | the bar's timestamp, copied from the input |
|
|
175
|
+
| buySetup | integer | buy setup counter (0 or more; exactly 9 marks a setup 9) |
|
|
176
|
+
| sellSetup | integer | sell setup counter, same meaning |
|
|
177
|
+
| buyCountdown | integer | signed buy countdown value; 13 means just completed; 14 or more means no countdown in progress |
|
|
178
|
+
| sellCountdown | integer | signed sell countdown value, same meaning |
|
|
179
|
+
| resistance | number or null | price of the active latest resistance level |
|
|
180
|
+
| support | number or null | price of the active latest support level |
|
|
181
|
+
| buyDeferred | boolean | true on a bar where the buy countdown was held at -12 by the 13-versus-8 test |
|
|
182
|
+
| sellDeferred | boolean | same for the sell countdown |
|
|
183
|
+
| buyPerfected | boolean | true only on a buy setup 9 bar whose bar 8 or bar 9 low is strictly below both the bar 6 low and the bar 7 low (bars numbered 1 to 9 within the setup) |
|
|
184
|
+
| sellPerfected | boolean | true only on a sell setup 9 bar whose bar 8 or bar 9 high is strictly above both the bar 6 high and the bar 7 high |
|
|
185
|
+
| bullishFlip | boolean | true when the previous bar closed below the close 4 bars before it and this bar closes above the close 4 bars earlier (needs 5 earlier bars) |
|
|
186
|
+
| bearishFlip | boolean | the mirror: previous close above its 4-bars-earlier close, this close below its 4-bars-earlier close |
|
|
187
|
+
|
|
188
|
+
The four fields above are information only. They never change a setup, countdown or level value, and a setup does not need a flip to start.
|
|
189
|
+
|
|
190
|
+
Notes for implementers:
|
|
191
|
+
|
|
192
|
+
- Prices are compared as plain floating-point numbers with no rounding.
|
|
193
|
+
- A bar where the countdown is cancelled or restarted is reported with that
|
|
194
|
+
bar's own result; there is no look-ahead and results never change when later
|
|
195
|
+
bars arrive.
|
|
196
|
+
- Counting from a different starting bar can change early results (a run that
|
|
197
|
+
began before the first bar is invisible). Compare implementations only on the
|
|
198
|
+
same bar list, started from the same first bar.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "td-sequential"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "TD Sequential indicator for Python: TD9 setup, countdown 13 and TDST levels on OHLC candles. Tested, zero dependencies."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Moolish", email = "support@moolish.com" }]
|
|
14
|
+
keywords = [
|
|
15
|
+
"td-sequential", "tdsequential", "td9", "td-setup", "td-countdown", "tdst", "tom-demark",
|
|
16
|
+
"technical-analysis", "indicator", "trading", "crypto", "stocks", "forex", "ohlc", "pandas",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 5 - Production/Stable",
|
|
20
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.9",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Typing :: Typed",
|
|
32
|
+
]
|
|
33
|
+
dependencies = []
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
pandas = ["pandas>=1.5"]
|
|
37
|
+
test = ["pytest>=7", "pandas>=1.5"]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://moolish.com/tools/td-sequential-counter/"
|
|
41
|
+
Documentation = "https://moolish.com/learn/td-sequential/"
|
|
42
|
+
Source = "https://github.com/moolish-com/td-sequential-python"
|
|
43
|
+
Issues = "https://github.com/moolish-com/td-sequential-python/issues"
|
|
44
|
+
Changelog = "https://github.com/moolish-com/td-sequential-python/blob/main/CHANGELOG.md"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["src/td_sequential"]
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.sdist]
|
|
50
|
+
include = ["src", "tests", "SPEC.md", "README.md", "CHANGELOG.md", "LICENSE"]
|
|
51
|
+
|
|
52
|
+
[tool.pytest.ini_options]
|
|
53
|
+
pythonpath = ["src"]
|
|
54
|
+
testpaths = ["tests"]
|