tradingview-mcp 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,382 @@
1
+ """
2
+ Utility functions for TradingView MCP.
3
+
4
+ Provides helper functions for data processing, validation, and technical analysis.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, Optional
10
+
11
+ from tradingview_mcp.constants import (
12
+ ALLOWED_TIMEFRAMES,
13
+ EXCHANGE_SCREENER,
14
+ MARKETS,
15
+ TIMEFRAME_MAP,
16
+ )
17
+
18
+
19
+ def sanitize_timeframe(tf: str | None, default: str = "15m") -> str:
20
+ """
21
+ Validate and sanitize a timeframe string.
22
+
23
+ Args:
24
+ tf: Timeframe to validate
25
+ default: Default value if invalid
26
+
27
+ Returns:
28
+ Valid timeframe string
29
+ """
30
+ if not tf:
31
+ return default
32
+ tf = tf.strip()
33
+ return tf if tf in ALLOWED_TIMEFRAMES else default
34
+
35
+
36
+ def sanitize_exchange(ex: str | None, default: str = "america") -> str:
37
+ """
38
+ Validate and sanitize an exchange name.
39
+
40
+ Args:
41
+ ex: Exchange to validate
42
+ default: Default value if invalid
43
+
44
+ Returns:
45
+ Valid exchange/market string
46
+ """
47
+ if not ex:
48
+ return default
49
+ ex = ex.strip().lower()
50
+ if ex in EXCHANGE_SCREENER:
51
+ return ex
52
+ if ex in MARKETS:
53
+ return ex
54
+ return default
55
+
56
+
57
+ def sanitize_market(market: str | None, default: str = "america") -> str:
58
+ """
59
+ Validate and sanitize a market name.
60
+
61
+ Args:
62
+ market: Market to validate
63
+ default: Default value if invalid
64
+
65
+ Returns:
66
+ Valid market string
67
+ """
68
+ if not market:
69
+ return default
70
+ market = market.strip().lower()
71
+ return market if market in MARKETS else default
72
+
73
+
74
+ def timeframe_to_resolution(tf: str) -> str:
75
+ """
76
+ Convert timeframe to TradingView API resolution.
77
+
78
+ Args:
79
+ tf: Timeframe string (e.g., '15m', '1h', '4h', '1D')
80
+
81
+ Returns:
82
+ TradingView resolution string
83
+ """
84
+ return TIMEFRAME_MAP.get(tf, tf)
85
+
86
+
87
+ def get_screener_for_exchange(exchange: str) -> str:
88
+ """
89
+ Get the screener market for an exchange.
90
+
91
+ Args:
92
+ exchange: Exchange name (e.g., 'binance', 'nasdaq')
93
+
94
+ Returns:
95
+ Screener market (e.g., 'crypto', 'america')
96
+ """
97
+ return EXCHANGE_SCREENER.get(exchange.lower(), "america")
98
+
99
+
100
+ def format_technical_rating(rating: float) -> str:
101
+ """
102
+ Convert numeric technical rating to human-readable format.
103
+
104
+ Args:
105
+ rating: Rating value (-1 to 1)
106
+
107
+ Returns:
108
+ Rating label (Strong Buy, Buy, Neutral, Sell, Strong Sell)
109
+ """
110
+ if rating >= 0.5:
111
+ return "Strong Buy"
112
+ elif rating >= 0.1:
113
+ return "Buy"
114
+ elif rating >= -0.1:
115
+ return "Neutral"
116
+ elif rating >= -0.5:
117
+ return "Sell"
118
+ else:
119
+ return "Strong Sell"
120
+
121
+
122
+ def compute_percent_change(open_price: float, close_price: float) -> float:
123
+ """
124
+ Calculate percentage change.
125
+
126
+ Args:
127
+ open_price: Starting price
128
+ close_price: Ending price
129
+
130
+ Returns:
131
+ Percentage change
132
+ """
133
+ if not open_price or open_price == 0:
134
+ return 0.0
135
+ return ((close_price - open_price) / open_price) * 100
136
+
137
+
138
+ def compute_bollinger_band_width(sma: float, bb_upper: float, bb_lower: float) -> Optional[float]:
139
+ """
140
+ Calculate Bollinger Band Width (BBW).
141
+
142
+ BBW = (Upper Band - Lower Band) / SMA20
143
+
144
+ Args:
145
+ sma: SMA20 (middle band)
146
+ bb_upper: Upper Bollinger Band
147
+ bb_lower: Lower Bollinger Band
148
+
149
+ Returns:
150
+ BBW value or None if calculation fails
151
+ """
152
+ if not sma or sma == 0:
153
+ return None
154
+ try:
155
+ return (bb_upper - bb_lower) / sma
156
+ except (TypeError, ZeroDivisionError):
157
+ return None
158
+
159
+
160
+ def compute_bollinger_rating(
161
+ close: float, bb_upper: float, bb_middle: float, bb_lower: float
162
+ ) -> tuple[int, str]:
163
+ """
164
+ Calculate Bollinger Band position rating and signal.
165
+
166
+ Rating scale:
167
+ - +3: Price above upper band (Strong overbought)
168
+ - +2: Price in upper half above middle (Overbought)
169
+ - +1: Price slightly above middle (Weak bullish)
170
+ - -1: Price slightly below middle (Weak bearish)
171
+ - -2: Price in lower half below middle (Oversold)
172
+ - -3: Price below lower band (Strong oversold)
173
+
174
+ Args:
175
+ close: Current price
176
+ bb_upper: Upper band
177
+ bb_middle: Middle band (SMA20)
178
+ bb_lower: Lower band
179
+
180
+ Returns:
181
+ Tuple of (rating, signal)
182
+ """
183
+ rating = 0
184
+ signal = "NEUTRAL"
185
+
186
+ if close > bb_upper:
187
+ rating = 3
188
+ signal = "STRONG_OVERBOUGHT"
189
+ elif close > bb_middle + ((bb_upper - bb_middle) / 2):
190
+ rating = 2
191
+ signal = "BUY"
192
+ elif close > bb_middle:
193
+ rating = 1
194
+ signal = "WEAK_BUY"
195
+ elif close < bb_lower:
196
+ rating = -3
197
+ signal = "STRONG_OVERSOLD"
198
+ elif close < bb_middle - ((bb_middle - bb_lower) / 2):
199
+ rating = -2
200
+ signal = "SELL"
201
+ elif close < bb_middle:
202
+ rating = -1
203
+ signal = "WEAK_SELL"
204
+
205
+ return rating, signal
206
+
207
+
208
+ def compute_rsi_signal(rsi: float) -> str:
209
+ """
210
+ Determine RSI signal.
211
+
212
+ Args:
213
+ rsi: RSI value (0-100)
214
+
215
+ Returns:
216
+ Signal string
217
+ """
218
+ if rsi >= 80:
219
+ return "EXTREMELY_OVERBOUGHT"
220
+ elif rsi >= 70:
221
+ return "OVERBOUGHT"
222
+ elif rsi >= 60:
223
+ return "BULLISH"
224
+ elif rsi <= 20:
225
+ return "EXTREMELY_OVERSOLD"
226
+ elif rsi <= 30:
227
+ return "OVERSOLD"
228
+ elif rsi <= 40:
229
+ return "BEARISH"
230
+ else:
231
+ return "NEUTRAL"
232
+
233
+
234
+ def compute_macd_signal(macd: float, signal: float) -> str:
235
+ """
236
+ Determine MACD signal.
237
+
238
+ Args:
239
+ macd: MACD line value
240
+ signal: Signal line value
241
+
242
+ Returns:
243
+ Signal string
244
+ """
245
+ diff = macd - signal
246
+ if diff > 0:
247
+ if macd > 0:
248
+ return "STRONG_BULLISH"
249
+ return "BULLISH"
250
+ elif diff < 0:
251
+ if macd < 0:
252
+ return "STRONG_BEARISH"
253
+ return "BEARISH"
254
+ return "NEUTRAL"
255
+
256
+
257
+ def analyze_indicators(indicators: dict[str, Any]) -> dict[str, Any]:
258
+ """
259
+ Perform comprehensive technical analysis on indicator data.
260
+
261
+ Args:
262
+ indicators: Dictionary of indicator values
263
+
264
+ Returns:
265
+ Analysis results with signals and ratings
266
+ """
267
+ result: dict[str, Any] = {"signals": [], "rating": 0, "recommendation": "NEUTRAL"}
268
+
269
+ # Extract values
270
+ close = indicators.get("close", 0)
271
+ open_price = indicators.get("open", 0)
272
+ high = indicators.get("high", 0)
273
+ low = indicators.get("low", 0)
274
+ volume = indicators.get("volume", 0)
275
+ rsi = indicators.get("RSI", 50)
276
+ macd = indicators.get("MACD.macd", 0)
277
+ macd_signal = indicators.get("MACD.signal", 0)
278
+ bb_upper = indicators.get("BB.upper", 0)
279
+ bb_lower = indicators.get("BB.lower", 0)
280
+ sma20 = indicators.get("SMA20", close)
281
+ ema50 = indicators.get("EMA50", close)
282
+ ema200 = indicators.get("EMA200", close)
283
+ adx = indicators.get("ADX", 0)
284
+
285
+ # Price change
286
+ if open_price and close:
287
+ change = compute_percent_change(open_price, close)
288
+ result["change_percent"] = round(change, 2)
289
+
290
+ # RSI Analysis
291
+ if rsi:
292
+ rsi_signal = compute_rsi_signal(rsi)
293
+ result["rsi_signal"] = rsi_signal
294
+ if "OVERBOUGHT" in rsi_signal:
295
+ result["signals"].append(f"RSI Overbought ({rsi:.1f})")
296
+ result["rating"] -= 1
297
+ elif "OVERSOLD" in rsi_signal:
298
+ result["signals"].append(f"RSI Oversold ({rsi:.1f})")
299
+ result["rating"] += 1
300
+
301
+ # MACD Analysis
302
+ if macd and macd_signal:
303
+ macd_sig = compute_macd_signal(macd, macd_signal)
304
+ result["macd_signal"] = macd_sig
305
+ if "BULLISH" in macd_sig:
306
+ result["signals"].append(f"MACD Bullish")
307
+ result["rating"] += 1
308
+ elif "BEARISH" in macd_sig:
309
+ result["signals"].append(f"MACD Bearish")
310
+ result["rating"] -= 1
311
+
312
+ # Bollinger Band Analysis
313
+ if bb_upper and bb_lower and sma20 and close:
314
+ bb_rating, bb_signal = compute_bollinger_rating(close, bb_upper, sma20, bb_lower)
315
+ bbw = compute_bollinger_band_width(sma20, bb_upper, bb_lower)
316
+ result["bb_rating"] = bb_rating
317
+ result["bb_signal"] = bb_signal
318
+ result["bbw"] = round(bbw, 4) if bbw else None
319
+
320
+ if bb_rating >= 2:
321
+ result["signals"].append("Price near/above upper BB")
322
+ result["rating"] -= 1
323
+ elif bb_rating <= -2:
324
+ result["signals"].append("Price near/below lower BB")
325
+ result["rating"] += 1
326
+
327
+ if bbw and bbw < 0.02:
328
+ result["signals"].append("BB Squeeze (low volatility)")
329
+
330
+ # Moving Average Analysis
331
+ if close and sma20 and ema50 and ema200:
332
+ if close > sma20 > ema50 > ema200:
333
+ result["signals"].append("Strong uptrend (above all MAs)")
334
+ result["rating"] += 2
335
+ elif close < sma20 < ema50 < ema200:
336
+ result["signals"].append("Strong downtrend (below all MAs)")
337
+ result["rating"] -= 2
338
+ elif close > ema200:
339
+ result["signals"].append("Above EMA200 (long-term bullish)")
340
+ result["rating"] += 1
341
+ elif close < ema200:
342
+ result["signals"].append("Below EMA200 (long-term bearish)")
343
+ result["rating"] -= 1
344
+
345
+ # ADX Trend Strength
346
+ if adx:
347
+ if adx > 50:
348
+ result["signals"].append(f"Very strong trend (ADX: {adx:.1f})")
349
+ elif adx > 25:
350
+ result["signals"].append(f"Trending market (ADX: {adx:.1f})")
351
+ else:
352
+ result["signals"].append(f"Ranging/weak trend (ADX: {adx:.1f})")
353
+
354
+ # Final recommendation
355
+ if result["rating"] >= 3:
356
+ result["recommendation"] = "STRONG_BUY"
357
+ elif result["rating"] >= 1:
358
+ result["recommendation"] = "BUY"
359
+ elif result["rating"] <= -3:
360
+ result["recommendation"] = "STRONG_SELL"
361
+ elif result["rating"] <= -1:
362
+ result["recommendation"] = "SELL"
363
+ else:
364
+ result["recommendation"] = "NEUTRAL"
365
+
366
+ return result
367
+
368
+
369
+ def format_symbol(symbol: str, exchange: str) -> str:
370
+ """
371
+ Format a symbol with exchange prefix if needed.
372
+
373
+ Args:
374
+ symbol: Symbol (e.g., 'BTCUSDT' or 'BINANCE:BTCUSDT')
375
+ exchange: Exchange name
376
+
377
+ Returns:
378
+ Formatted symbol (e.g., 'BINANCE:BTCUSDT')
379
+ """
380
+ if ":" in symbol:
381
+ return symbol.upper()
382
+ return f"{exchange.upper()}:{symbol.upper()}"
@@ -0,0 +1,182 @@
1
+ Metadata-Version: 2.4
2
+ Name: tradingview-mcp
3
+ Version: 1.0.0
4
+ Summary: A comprehensive MCP server for TradingView market screening with integrated screener functionality
5
+ Author: TradingView MCP Team
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: crypto,mcp,screener,stocks,technical-analysis,trading,tradingview
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Financial and Insurance Industry
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Office/Business :: Financial :: Investment
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: httpx>=0.24.0
20
+ Requires-Dist: mcp>=1.0.0
21
+ Requires-Dist: pandas>=2.0.0
22
+ Requires-Dist: requests>=2.28.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: pyright>=1.1.0; extra == 'dev'
25
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
26
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
27
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # TradingView MCP Server
31
+
32
+ A comprehensive Model Context Protocol (MCP) server for TradingView market screening with fully integrated screener functionality. This server provides powerful tools for cryptocurrency and stock market analysis directly through the MCP interface.
33
+
34
+ ## Features
35
+
36
+ ### Core Screener Functionality
37
+ - **Direct TradingView API Integration**: Query the TradingView scanner API without external dependencies
38
+ - **Multi-Market Support**: 76+ markets including crypto, stocks, forex, futures, and bonds
39
+ - **SQL-like Query Interface**: Build complex queries with filtering, sorting, and pagination
40
+ - **250+ Technical Indicators**: Access a comprehensive set of technical analysis columns
41
+
42
+ ### MCP Tools
43
+ - `screen_market`: Execute custom market screening queries
44
+ - `get_top_gainers`: Find top gaining assets in any market
45
+ - `get_top_losers`: Find top losing assets in any market
46
+ - `get_premarket_movers`: Pre-market gainers, losers, and most active
47
+ - `get_postmarket_movers`: Post-market activity analysis
48
+ - `get_technical_analysis`: Detailed technical analysis for specific symbols
49
+ - `scan_bollinger_bands`: Bollinger Band squeeze detection
50
+ - `scan_volume_breakout`: Volume breakout detection
51
+ - `scan_rsi_extremes`: RSI overbought/oversold scanner
52
+ - `scan_macd_crossover`: MACD crossover detection
53
+ - `get_all_symbols`: Retrieve all symbols for a market
54
+ - `advanced_query`: Execute advanced queries with AND/OR logic
55
+
56
+ ### MCP Resources
57
+ - `markets://list`: List all available markets
58
+ - `columns://list`: List all available technical indicator columns
59
+ - `exchanges://crypto`: List cryptocurrency exchanges
60
+ - `presets://list`: List predefined screening presets
61
+
62
+ ## Installation
63
+
64
+ ### Using uv (Recommended)
65
+ ```bash
66
+ uv add tradingview-mcp
67
+ ```
68
+
69
+ ### Using pip
70
+ ```bash
71
+ pip install tradingview-mcp
72
+ ```
73
+
74
+ ### From Source
75
+ ```bash
76
+ git clone https://github.com/your-repo/tradingview-mcp.git
77
+ cd tradingview-mcp
78
+ uv sync
79
+ ```
80
+
81
+ ## Usage
82
+
83
+ ### Running the MCP Server
84
+
85
+ #### Stdio Transport (Default)
86
+ ```bash
87
+ tradingview-mcp
88
+ ```
89
+
90
+ #### HTTP Transport
91
+ ```bash
92
+ tradingview-mcp streamable-http --host 127.0.0.1 --port 8000
93
+ ```
94
+
95
+ ### MCP Client Configuration
96
+
97
+ Add to your MCP client configuration:
98
+
99
+ ```json
100
+ {
101
+ "mcpServers": {
102
+ "tradingview": {
103
+ "command": "tradingview-mcp",
104
+ "args": []
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ ### Example Queries
111
+
112
+ #### Basic Market Screening
113
+ ```python
114
+ # Get top 50 stocks by trading volume
115
+ await client.call_tool("screen_market", {
116
+ "market": "america",
117
+ "columns": ["name", "close", "volume", "change"],
118
+ "sort_by": "volume",
119
+ "ascending": False,
120
+ "limit": 50
121
+ })
122
+ ```
123
+
124
+ #### Technical Analysis Screening
125
+ ```python
126
+ # Find stocks with RSI below 30 (oversold)
127
+ await client.call_tool("scan_rsi_extremes", {
128
+ "market": "america",
129
+ "condition": "oversold",
130
+ "threshold": 30,
131
+ "limit": 20
132
+ })
133
+ ```
134
+
135
+ #### Cryptocurrency Screening
136
+ ```python
137
+ # Get top crypto gainers
138
+ await client.call_tool("get_top_gainers", {
139
+ "market": "crypto",
140
+ "limit": 25
141
+ })
142
+ ```
143
+
144
+ ## API Reference
145
+
146
+ ### Markets
147
+ The following markets are supported:
148
+ - **Crypto**: `crypto`, `coin`
149
+ - **Traditional Finance**: `america`, `uk`, `germany`, `japan`, etc. (67 countries)
150
+ - **Other**: `forex`, `futures`, `bonds`, `cfd`, `options`
151
+
152
+ ### Technical Indicators
153
+ Common indicators include:
154
+ - Price: `open`, `high`, `low`, `close`, `volume`
155
+ - Moving Averages: `SMA5`, `SMA10`, `SMA20`, `SMA50`, `SMA100`, `SMA200`, `EMA5`, `EMA10`, `EMA20`, `EMA50`, `EMA100`, `EMA200`
156
+ - Oscillators: `RSI`, `RSI7`, `MACD.macd`, `MACD.signal`, `Stoch.K`, `Stoch.D`
157
+ - Bollinger Bands: `BB.upper`, `BB.lower`
158
+ - Others: `VWAP`, `ATR`, `ADX`, `CCI20`, etc.
159
+
160
+ See `columns://list` resource for the complete list.
161
+
162
+ ## Development
163
+
164
+ ### Running Tests
165
+ ```bash
166
+ uv run pytest tests/
167
+ ```
168
+
169
+ ### Code Formatting
170
+ ```bash
171
+ uv run ruff format .
172
+ uv run ruff check . --fix
173
+ ```
174
+
175
+ ### Type Checking
176
+ ```bash
177
+ uv run pyright
178
+ ```
179
+
180
+ ## License
181
+
182
+ MIT License - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,13 @@
1
+ tradingview_mcp/__init__.py,sha256=V7RLq22Qp1rsMhDYNlXfWkiNaXlo7s4KkNUmSvbGKIM,455
2
+ tradingview_mcp/column.py,sha256=MC7lWksmyaYF4SkVm97Apr8httwip-N-4aVTSyS0CQo,8871
3
+ tradingview_mcp/constants.py,sha256=yGzC9Zie825JqqHKGWukTz4HicGKn0pDiUn8op_Me2Y,12749
4
+ tradingview_mcp/models.py,sha256=CHSQ46A2ljhvzI6YP8XRItUdoDJw1yYebiBANt9xeD0,3366
5
+ tradingview_mcp/query.py,sha256=gkC4t-2_jtuUK3KgzU62wrIcGoaOmY--1EwAshGQb0Q,10871
6
+ tradingview_mcp/scanner.py,sha256=CA8GP-N8uCYacpuUzll9IfalKK0hEUSU9ViVEAO8mwU,7535
7
+ tradingview_mcp/server.py,sha256=xOZ0Vm_RicRVMCyq6y0DKUPpE5gUtAVrERdItmHLdUs,40516
8
+ tradingview_mcp/utils.py,sha256=6O89qIaZ_eYoN3m12r2q4-D8VpJajP5WuwKQbj4ZVHo,10238
9
+ tradingview_mcp-1.0.0.dist-info/METADATA,sha256=vfzUAYJaI5uIz1tPVq1zmjiaU1zK1nAZlhoRLDldk_o,5097
10
+ tradingview_mcp-1.0.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
11
+ tradingview_mcp-1.0.0.dist-info/entry_points.txt,sha256=GZxjGqgVbUlWDp5OzFQoCN_g1UBLyOmfVqCR5uzscnU,57
12
+ tradingview_mcp-1.0.0.dist-info/licenses/LICENSE,sha256=ma04jhucIafnA2IaYn--PlxmCUpqhESjKAu4d0c_Ib4,1141
13
+ tradingview_mcp-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ tradingview-mcp = tradingview_mcp:main
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Shneor Elmaleh
4
+ Copyright (c) 2025 Ahmet Taner Atila
5
+ Copyright (c) 2026 Henrik (k73a)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.