investfly-sdk 1.5__tar.gz → 1.7__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.
Files changed (48) hide show
  1. {investfly_sdk-1.5 → investfly_sdk-1.7}/PKG-INFO +15 -5
  2. {investfly_sdk-1.5 → investfly_sdk-1.7}/README.md +12 -1
  3. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/IndicatorApiClient.py +12 -1
  4. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/RestApiClient.py +2 -1
  5. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/cli/InvestflyCli.py +40 -11
  6. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/MarketData.py +9 -8
  7. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/ModelUtils.py +9 -6
  8. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/indicators/RsiOfSma.py +3 -7
  9. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/indicators/SmaEmaAverage.py +3 -6
  10. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly_sdk.egg-info/PKG-INFO +15 -5
  11. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly_sdk.egg-info/SOURCES.txt +2 -1
  12. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly_sdk.egg-info/requires.txt +1 -2
  13. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly_sdk.egg-info/top_level.txt +1 -0
  14. {investfly_sdk-1.5 → investfly_sdk-1.7}/pyproject.toml +8 -4
  15. investfly_sdk-1.7/talib/__init__.pyi +185 -0
  16. {investfly_sdk-1.5 → investfly_sdk-1.7}/LICENSE.txt +0 -0
  17. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/__init__.py +0 -0
  18. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/InvestflyApiClient.py +0 -0
  19. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/MarketDataApiClient.py +0 -0
  20. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/PortfolioApiClient.py +0 -0
  21. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/StrategyApiClient.py +0 -0
  22. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/__init__.py +0 -0
  23. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/api/py.typed +0 -0
  24. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/cli/__init__.py +0 -0
  25. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/CommonModels.py +0 -0
  26. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/Indicator.py +0 -0
  27. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/MarketDataIds.py +0 -0
  28. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/PortfolioModels.py +0 -0
  29. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/SecurityFilterModels.py +0 -0
  30. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/SecurityUniverseSelector.py +0 -0
  31. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/StrategyModels.py +0 -0
  32. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/TradingStrategy.py +0 -0
  33. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/__init__.py +0 -0
  34. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/models/py.typed +0 -0
  35. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/__init__.py +0 -0
  36. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/indicators/IndicatorTemplate.py +0 -0
  37. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/indicators/NewsSentiment.py +0 -0
  38. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/indicators/__init__.py +0 -0
  39. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/strategies/SmaCrossOverStrategy.py +0 -0
  40. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/strategies/SmaCrossOverTemplate.py +0 -0
  41. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/samples/strategies/__init__.py +0 -0
  42. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/utils/CommonUtils.py +0 -0
  43. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/utils/PercentBasedPortfolioAllocator.py +0 -0
  44. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/utils/__init__.py +0 -0
  45. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly/utils/py.typed +0 -0
  46. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly_sdk.egg-info/dependency_links.txt +0 -0
  47. {investfly_sdk-1.5 → investfly_sdk-1.7}/investfly_sdk.egg-info/entry_points.txt +0 -0
  48. {investfly_sdk-1.5 → investfly_sdk-1.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: investfly-sdk
3
- Version: 1.5
3
+ Version: 1.7
4
4
  Summary: Investfly SDK
5
5
  Author-email: "Investfly.com" <admin@investfly.com>
6
6
  License: The MIT License (MIT)
@@ -36,7 +36,6 @@ Requires-Dist: charset-normalizer==3.2.0
36
36
  Requires-Dist: idna==3.4
37
37
  Requires-Dist: pandas==2.0.3
38
38
  Requires-Dist: pandas-stubs==2.0.3.230814
39
- Requires-Dist: pandas-ta==0.3.14b0
40
39
  Requires-Dist: python-dateutil==2.8.2
41
40
  Requires-Dist: pytz==2023.3
42
41
  Requires-Dist: requests==2.31.0
@@ -45,7 +44,7 @@ Requires-Dist: six==1.16.0
45
44
  Requires-Dist: tzdata==2023.3
46
45
  Requires-Dist: urllib3==1.26.15
47
46
  Requires-Dist: numpy==1.26.4
48
- Requires-Dist: TA-Lib==0.4.28
47
+ Requires-Dist: mypy==1.12.1
49
48
 
50
49
  # About
51
50
 
@@ -182,13 +181,24 @@ Using IDE editor will assist with auto-completion and type hints. Additionally,
182
181
  When using the IDE, open `investfly` directory created above as a project with your IDE.
183
182
  Make sure that Python Interpreter is configured to the virtual environment `investfly/venv/bin/python` created above.
184
183
 
184
+ ### TA-Lib Stubs
185
+ TA-Lib is a technical analysis library https://github.com/TA-Lib/ta-lib-python used to compute technical indicators by Investfly.
186
+ This library can also be used in custom indicators and strategies. However, installing Python ta-lib wrapper requires installing native ta-lib, which is challenging based on the OS you are working with.
187
+ So investfly-sdk ships with ta-lib stubs, so when you install investfly-sdk, pip does not try to install ta-lib.
188
+ This means that you can develop your code, but cannot run them locally if you are using ta-lib in your code. This is generally OK, because you will use the CLI
189
+ to upload your code to Investfly server, where it will be run.
190
+ If you want also want to run your code locally to test it, then follow the installation method described in the link above and then install ta-lib with the following command
191
+ ```commandline
192
+ pip install ta-lib==0.4.28
193
+ ```
194
+
185
195
 
186
196
  # API Docs
187
197
 
188
198
  API Docs are published at https://www.investfly.com/guides/docs/index.html
189
199
 
190
200
  # Getting Help
191
- Please email [admin@investfly.com](admin@investfly.com) for any support or bug report
201
+ Please email support@investfly.com for any support or bug report
192
202
 
193
203
 
194
204
 
@@ -133,13 +133,24 @@ Using IDE editor will assist with auto-completion and type hints. Additionally,
133
133
  When using the IDE, open `investfly` directory created above as a project with your IDE.
134
134
  Make sure that Python Interpreter is configured to the virtual environment `investfly/venv/bin/python` created above.
135
135
 
136
+ ### TA-Lib Stubs
137
+ TA-Lib is a technical analysis library https://github.com/TA-Lib/ta-lib-python used to compute technical indicators by Investfly.
138
+ This library can also be used in custom indicators and strategies. However, installing Python ta-lib wrapper requires installing native ta-lib, which is challenging based on the OS you are working with.
139
+ So investfly-sdk ships with ta-lib stubs, so when you install investfly-sdk, pip does not try to install ta-lib.
140
+ This means that you can develop your code, but cannot run them locally if you are using ta-lib in your code. This is generally OK, because you will use the CLI
141
+ to upload your code to Investfly server, where it will be run.
142
+ If you want also want to run your code locally to test it, then follow the installation method described in the link above and then install ta-lib with the following command
143
+ ```commandline
144
+ pip install ta-lib==0.4.28
145
+ ```
146
+
136
147
 
137
148
  # API Docs
138
149
 
139
150
  API Docs are published at https://www.investfly.com/guides/docs/index.html
140
151
 
141
152
  # Getting Help
142
- Please email [admin@investfly.com](admin@investfly.com) for any support or bug report
153
+ Please email support@investfly.com for any support or bug report
143
154
 
144
155
 
145
156
 
@@ -9,13 +9,24 @@ class IndicatorApiClient:
9
9
  def __init__(self, restApiClient: RestApiClient) -> None:
10
10
  self.restApiClient = restApiClient
11
11
 
12
- def listIndicators(self) -> List[IndicatorSpec]:
12
+ def listCustomIndicators(self) -> List[IndicatorSpec]:
13
13
  indicatorsListDict = self.restApiClient.doGet('/indicator/list/custom')
14
14
  result: List[IndicatorSpec] = []
15
15
  for indicatorDict in indicatorsListDict:
16
16
  result.append(IndicatorSpec.fromDict(indicatorDict))
17
17
  return result
18
18
 
19
+ def listStandardIndicators(self) -> List[IndicatorSpec]:
20
+ indicatorsListDict = self.restApiClient.doGet('/indicator/list/standard')
21
+ result: List[IndicatorSpec] = []
22
+ for indicatorDict in indicatorsListDict:
23
+ result.append(IndicatorSpec.fromDict(indicatorDict))
24
+ return result
25
+
26
+ def getIndicatorSpec(self, indicatorId: str) -> IndicatorSpec:
27
+ specDict = self.restApiClient.doGet(f'/indicator/{indicatorId}')
28
+ return IndicatorSpec.fromDict(specDict)
29
+
19
30
  def getIndicatorCode(self, indicatorId: str) -> str:
20
31
  return self.restApiClient.doGet(f'/indicator/custom/{indicatorId}/code')
21
32
 
@@ -19,11 +19,12 @@ class RestApiClient:
19
19
 
20
20
  def __init__(self, baseUrl: str) -> None:
21
21
  self.headers: Dict[str, str] = {}
22
+ self.headers['client-mode'] = 'api'
22
23
  self.baseUrl = baseUrl
23
24
  self.log = logging.getLogger(self.__class__.__name__)
24
25
 
25
26
  def login(self, username: str, password: str) -> Session:
26
- res = requests.post(self.baseUrl + "/user/login", auth=(username, password), verify=False)
27
+ res = requests.post(self.baseUrl + "/user/login", auth=(username, password), headers=self.headers, verify=False)
27
28
  if res.status_code == 200:
28
29
  self.headers['investfly-client-id'] = res.headers['investfly-client-id']
29
30
  self.headers['investfly-client-token'] = res.headers['investfly-client-token']
@@ -1,6 +1,4 @@
1
1
  import argparse
2
- import pickle
3
- import os.path
4
2
  import time
5
3
  from typing import List, cast
6
4
 
@@ -12,6 +10,8 @@ from investfly import samples
12
10
  import inspect
13
11
  from pathlib import Path
14
12
  import shutil
13
+ import json
14
+ import re
15
15
 
16
16
 
17
17
  class InvestflyCli:
@@ -20,6 +20,15 @@ class InvestflyCli:
20
20
  self.running: bool = True
21
21
  self.investflyApi = InvestflyApiClient()
22
22
 
23
+ @staticmethod
24
+ def extract_class_name(source_code: str, base_class: str) -> str|None:
25
+ class_pattern = re.compile(r'class\s+(\w+)\s*\(\s*' + base_class + r'\s*\)\s*:', re.IGNORECASE)
26
+ for line in source_code.splitlines():
27
+ match = class_pattern.search(line)
28
+ if match:
29
+ return match.group(1)
30
+ return None
31
+
23
32
 
24
33
  def __loginAction(self, args: argparse.Namespace) -> Session:
25
34
  username = args.username
@@ -51,10 +60,12 @@ class InvestflyCli:
51
60
  return "\n".join(strategiesDictList)
52
61
 
53
62
  def __createStrategy(self, args: argparse.Namespace) -> str:
54
- name = args.name
55
63
  path = args.file
56
64
  with open(path, 'r') as source_file:
57
65
  code = source_file.read()
66
+ name = InvestflyCli.extract_class_name(code, "TradingStrategy")
67
+ if name is None:
68
+ return "Provided file does not contain class that extends from TradingStrategy"
58
69
  tradingStrategyModel = TradingStrategyModel(strategyName=name, strategyDesc=name, pythonCode=code)
59
70
  tradingStrategyModel = self.investflyApi.strategyApi.createStrategy(tradingStrategyModel)
60
71
  return f'Created strategy {tradingStrategyModel.strategyId}'
@@ -106,16 +117,28 @@ class InvestflyCli:
106
117
 
107
118
  # ==== INDICATOR COMMAND HANDLERS
108
119
 
109
- def __listIndicators(self, args: argparse.Namespace) -> str:
110
- indicators: List[IndicatorSpec] = self.investflyApi.indicatorApi.listIndicators()
120
+ def __listCustomIndicators(self, args: argparse.Namespace) -> str:
121
+ indicators: List[IndicatorSpec] = self.investflyApi.indicatorApi.listCustomIndicators()
122
+ idList = list(map(lambda spec: spec.indicatorId, indicators))
123
+ return str(idList)
124
+
125
+ def __listStandardIndicators(self, args: argparse.Namespace) -> str:
126
+ indicators: List[IndicatorSpec] = self.investflyApi.indicatorApi.listStandardIndicators()
111
127
  idList = list(map(lambda spec: spec.indicatorId, indicators))
112
128
  return str(idList)
113
129
 
130
+ def __getIndicatorSpec(self, args: argparse.Namespace) -> str:
131
+ spec = self.investflyApi.indicatorApi.getIndicatorSpec(args.id)
132
+ jsonDict = spec.toJsonDict()
133
+ return json.dumps(jsonDict, indent=2)
134
+
114
135
  def __createUpdateIndicator(self, args: argparse.Namespace):
115
136
  path = args.file
116
137
  with open(path, 'r') as source_file:
117
138
  code = source_file.read()
118
- self.investflyApi.indicatorApi.createUpdateIndicator(code)
139
+ spec = self.investflyApi.indicatorApi.createUpdateIndicator(code)
140
+ jsonDict = spec.toJsonDict()
141
+ return json.dumps(jsonDict, indent=2)
119
142
 
120
143
  def __downloadIndicatorCode(self, args: argparse.Namespace):
121
144
  indicatorId = args.id
@@ -149,7 +172,6 @@ class InvestflyCli:
149
172
  parser_listStrategies.set_defaults(func=self.__listStrategies)
150
173
 
151
174
  parser_createStrategy = subparser.add_parser('strategy.create', help='Create a new trading strategy')
152
- parser_createStrategy.add_argument('-n', '--name', required=True, help='Strategy Name')
153
175
  parser_createStrategy.add_argument('-f', '--file', required=True, help='Python File Path relative to the project root that contains strategy code')
154
176
  parser_createStrategy.set_defaults(func=self.__createStrategy)
155
177
 
@@ -177,15 +199,22 @@ class InvestflyCli:
177
199
 
178
200
  # ====== INDICATOR COMMANDS ====
179
201
 
180
- parser_listIndicators = subparser.add_parser('indicator.list', help='List Custom Indicators')
181
- parser_listIndicators.set_defaults(func=self.__listIndicators)
202
+ parser_listCustomIndicators = subparser.add_parser('indicator.listCustom', help='List Custom Indicators')
203
+ parser_listCustomIndicators.set_defaults(func=self.__listCustomIndicators)
204
+
205
+ parser_listStandardIndicators = subparser.add_parser('indicator.listStandard', help='List Custom Indicators')
206
+ parser_listStandardIndicators.set_defaults(func=self.__listStandardIndicators)
207
+
208
+ parser_getIndicatorSpec = subparser.add_parser('indicator.getIndicator', help="Get Indicator Specification")
209
+ parser_getIndicatorSpec.add_argument('-i', '--id', required=True, help='Indicator ID')
210
+ parser_getIndicatorSpec.set_defaults(func=self.__getIndicatorSpec)
182
211
 
183
212
  parser_downloadIndicator = subparser.add_parser('indicator.download', help='Download indicator python code and save it to a file')
184
- parser_downloadIndicator.add_argument('-i', '--id', required=True, help='IndicatorId ID')
213
+ parser_downloadIndicator.add_argument('-i', '--id', required=True, help='Indicator ID')
185
214
  parser_downloadIndicator.add_argument('-f', '--file', required=True, help='File path (with file name) to save indicator python code')
186
215
  parser_downloadIndicator.set_defaults(func=self.__downloadIndicatorCode)
187
216
 
188
- parser_createUpdateIndicator = subparser.add_parser('indicator.update', help='Create or update indicator. Indicator ID is retried from ClassName')
217
+ parser_createUpdateIndicator = subparser.add_parser('indicator.createupdate', help='Create or update indicator. Indicator ID is retried from ClassName')
189
218
  parser_createUpdateIndicator.add_argument('-f', '--file', required=True, help='File path (with file name) that contains indicator code')
190
219
  parser_createUpdateIndicator.set_defaults(func=self.__createUpdateIndicator)
191
220
 
@@ -65,21 +65,22 @@ class Quote:
65
65
  lastPrice: float
66
66
  prevClose: float| None = None
67
67
  todayChange: float | None = None
68
- todayChangePercent: float | None = None
68
+ todayChangePct: float | None = None
69
69
  dayOpen: float | None = None
70
70
  dayHigh: float | None = None
71
71
  dayLow: float | None = None
72
- dayVolume: int | None = None
72
+ volume: int | None = None
73
73
 
74
74
  @staticmethod
75
75
  def fromDict(jsonDict: Dict[str, Any]) -> Quote:
76
76
  quote = Quote(jsonDict["symbol"], parseDatetime(jsonDict["date"]), jsonDict["lastPrice"])
77
77
  quote.prevClose = jsonDict.get('prevClose')
78
78
  quote.todayChange = jsonDict.get("todayChange")
79
- quote.todayChangePercent = jsonDict.get('todayChangePercent')
79
+ quote.todayChangePct = jsonDict.get('todayChangePct')
80
80
  quote.dayOpen = jsonDict.get('dayOpen')
81
81
  quote.dayHigh = jsonDict.get('dayHigh')
82
82
  quote.dayLow = jsonDict.get('dayLow')
83
+ quote.volume = jsonDict.get('volume')
83
84
  return quote
84
85
 
85
86
  def toDict(self) -> Dict[str, Any]:
@@ -111,13 +112,13 @@ class Quote:
111
112
  raise Exception("DAY_CHANGE not available in Quote")
112
113
  return DatedValue(self.date, self.todayChange)
113
114
  elif quoteField == QuoteField.DAY_CHANGE_PCT:
114
- if self.todayChangePercent is None:
115
+ if self.todayChangePct is None:
115
116
  raise Exception("DAY_CHANGE_PCT value not available in Quote")
116
- return DatedValue(self.date, self.todayChangePercent)
117
+ return DatedValue(self.date, self.todayChangePct)
117
118
  elif quoteField == QuoteField.DAY_VOLUME:
118
- if self.dayVolume is None:
119
+ if self.volume is None:
119
120
  raise Exception("DAY_VOLUME not available in Quote")
120
- return DatedValue(self.date, self.dayVolume)
121
+ return DatedValue(self.date, self.volume)
121
122
  else:
122
123
  raise Exception("Invalid Quote Indicator ID: " + quoteField)
123
124
 
@@ -130,7 +131,7 @@ class Quote:
130
131
  bar['high'] = cast(float, self.dayHigh)
131
132
  bar['low'] = cast(float, self.dayLow)
132
133
  bar['close'] = cast(float, self.lastPrice)
133
- bar['volume'] = cast(int, self.dayVolume)
134
+ bar['volume'] = cast(int, self.volume)
134
135
  return bar
135
136
 
136
137
 
@@ -1,23 +1,26 @@
1
1
  from datetime import datetime
2
- import pytz
3
-
2
+ from zoneinfo import ZoneInfo
4
3
 
5
4
  class ModelUtils:
6
5
 
7
6
  # In Java, using Date includes timezone offset in JSON whereas using LocalDateTime does not
8
7
 
9
- est_tz = pytz.timezone('America/New_York')
8
+ est_zone = ZoneInfo("US/Eastern")
9
+
10
+ @staticmethod
11
+ def convertoToEst(dt: datetime) -> datetime:
12
+ return dt.astimezone(ModelUtils.est_zone)
10
13
 
11
14
  @staticmethod
12
15
  def localizeDateTime(dt: datetime) -> datetime:
13
- return ModelUtils.est_tz.localize(dt)
16
+ return dt.replace(tzinfo=ModelUtils.est_zone)
14
17
 
15
18
 
16
19
  @staticmethod
17
20
  def parseDatetime(date_str: str) -> datetime:
18
21
  dateFormat = '%Y-%m-%dT%H:%M:%S.%f' if "." in date_str else '%Y-%m-%dT%H:%M:%S'
19
22
  dt = datetime.strptime(date_str, dateFormat)
20
- dt = dt.astimezone(ModelUtils.est_tz)
23
+ dt = dt.astimezone(ModelUtils.est_zone)
21
24
  return dt
22
25
 
23
26
  @staticmethod
@@ -27,7 +30,7 @@ class ModelUtils:
27
30
  @staticmethod
28
31
  def parseZonedDatetime(date_str: str) -> datetime:
29
32
  dt = datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%S.%f%z')
30
- dt = dt.astimezone(ModelUtils.est_tz)
33
+ dt = dt.astimezone(ModelUtils.est_zone)
31
34
  return dt
32
35
 
33
36
  @staticmethod
@@ -14,14 +14,10 @@ from investfly.utils import *
14
14
 
15
15
  class RsiOfSma(Indicator):
16
16
 
17
-
18
- # To implement a price-based indicator (i.e. indicator that uses price bars [open,high,low,close,volume]),
19
- # you extend from PriceBasedIndicator and implement methods shown below
20
-
21
17
  def getIndicatorSpec(self) -> IndicatorSpec:
22
- # In this method, you must construct and return IndicatorDefinition object that specifies
23
- # indicator name, description and any parameters it needs. BarSize parameter is automatically
24
- # added from the parent class
18
+ # In this method, you must construct and return IndicatorSpec object that specifies
19
+ # indicator name, description and any parameters it needs. Stanard parameters like (barinterval, count, lookback)
20
+ # are automatically added
25
21
  indicator = IndicatorSpec("RSI of SMA")
26
22
  indicator.addParam("sma_period", IndicatorParamSpec(ParamType.INTEGER, True, 5, IndicatorParamSpec.PERIOD_VALUES))
27
23
  indicator.addParam("rsi_period", IndicatorParamSpec(ParamType.INTEGER, True, 10, IndicatorParamSpec.PERIOD_VALUES))
@@ -12,13 +12,10 @@ from investfly.utils import *
12
12
 
13
13
  class SmaEmaAverage(Indicator):
14
14
 
15
- # To implement a price-based indicator (i.e indicator that uses price bars [open,high,low,close,volume]) in
16
- # computation you extend from PriceBasedIndicator and implement methods shown below
17
-
18
15
  def getIndicatorSpec(self) -> IndicatorSpec:
19
- # In this method, you must construct and return IndicatorDefinition object that spefies
20
- # indicator name, description and any parameters it needs. BarSize parameter is automatically
21
- # added from the parent class
16
+ # In this method, you must construct and return IndicatorSpec object that specifies
17
+ # indicator name, description and any parameters it needs. Stanard parameters like (barinterval, count, lookback)
18
+ # are automatically added
22
19
  indicator = IndicatorSpec("SMA EMA Average")
23
20
  indicator.addParam('period', IndicatorParamSpec(ParamType.INTEGER, True, 5, IndicatorParamSpec.PERIOD_VALUES))
24
21
  return indicator
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: investfly-sdk
3
- Version: 1.5
3
+ Version: 1.7
4
4
  Summary: Investfly SDK
5
5
  Author-email: "Investfly.com" <admin@investfly.com>
6
6
  License: The MIT License (MIT)
@@ -36,7 +36,6 @@ Requires-Dist: charset-normalizer==3.2.0
36
36
  Requires-Dist: idna==3.4
37
37
  Requires-Dist: pandas==2.0.3
38
38
  Requires-Dist: pandas-stubs==2.0.3.230814
39
- Requires-Dist: pandas-ta==0.3.14b0
40
39
  Requires-Dist: python-dateutil==2.8.2
41
40
  Requires-Dist: pytz==2023.3
42
41
  Requires-Dist: requests==2.31.0
@@ -45,7 +44,7 @@ Requires-Dist: six==1.16.0
45
44
  Requires-Dist: tzdata==2023.3
46
45
  Requires-Dist: urllib3==1.26.15
47
46
  Requires-Dist: numpy==1.26.4
48
- Requires-Dist: TA-Lib==0.4.28
47
+ Requires-Dist: mypy==1.12.1
49
48
 
50
49
  # About
51
50
 
@@ -182,13 +181,24 @@ Using IDE editor will assist with auto-completion and type hints. Additionally,
182
181
  When using the IDE, open `investfly` directory created above as a project with your IDE.
183
182
  Make sure that Python Interpreter is configured to the virtual environment `investfly/venv/bin/python` created above.
184
183
 
184
+ ### TA-Lib Stubs
185
+ TA-Lib is a technical analysis library https://github.com/TA-Lib/ta-lib-python used to compute technical indicators by Investfly.
186
+ This library can also be used in custom indicators and strategies. However, installing Python ta-lib wrapper requires installing native ta-lib, which is challenging based on the OS you are working with.
187
+ So investfly-sdk ships with ta-lib stubs, so when you install investfly-sdk, pip does not try to install ta-lib.
188
+ This means that you can develop your code, but cannot run them locally if you are using ta-lib in your code. This is generally OK, because you will use the CLI
189
+ to upload your code to Investfly server, where it will be run.
190
+ If you want also want to run your code locally to test it, then follow the installation method described in the link above and then install ta-lib with the following command
191
+ ```commandline
192
+ pip install ta-lib==0.4.28
193
+ ```
194
+
185
195
 
186
196
  # API Docs
187
197
 
188
198
  API Docs are published at https://www.investfly.com/guides/docs/index.html
189
199
 
190
200
  # Getting Help
191
- Please email [admin@investfly.com](admin@investfly.com) for any support or bug report
201
+ Please email support@investfly.com for any support or bug report
192
202
 
193
203
 
194
204
 
@@ -42,4 +42,5 @@ investfly_sdk.egg-info/SOURCES.txt
42
42
  investfly_sdk.egg-info/dependency_links.txt
43
43
  investfly_sdk.egg-info/entry_points.txt
44
44
  investfly_sdk.egg-info/requires.txt
45
- investfly_sdk.egg-info/top_level.txt
45
+ investfly_sdk.egg-info/top_level.txt
46
+ talib/__init__.pyi
@@ -3,7 +3,6 @@ charset-normalizer==3.2.0
3
3
  idna==3.4
4
4
  pandas==2.0.3
5
5
  pandas-stubs==2.0.3.230814
6
- pandas-ta==0.3.14b0
7
6
  python-dateutil==2.8.2
8
7
  pytz==2023.3
9
8
  requests==2.31.0
@@ -12,4 +11,4 @@ six==1.16.0
12
11
  tzdata==2023.3
13
12
  urllib3==1.26.15
14
13
  numpy==1.26.4
15
- TA-Lib==0.4.28
14
+ mypy==1.12.1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "investfly-sdk"
7
- version = "1.5"
7
+ version = "1.7"
8
8
  description = "Investfly SDK"
9
9
  authors = [
10
10
  { name = "Investfly.com", email = "admin@investfly.com" },
@@ -23,7 +23,6 @@ dependencies = [
23
23
  "idna==3.4",
24
24
  "pandas==2.0.3",
25
25
  "pandas-stubs==2.0.3.230814",
26
- "pandas-ta==0.3.14b0",
27
26
  "python-dateutil==2.8.2",
28
27
  "pytz==2023.3",
29
28
  "requests==2.31.0",
@@ -32,10 +31,15 @@ dependencies = [
32
31
  "tzdata==2023.3",
33
32
  "urllib3==1.26.15",
34
33
  "numpy==1.26.4",
35
- "TA-Lib==0.4.28"
34
+ "mypy==1.12.1"
36
35
  ]
37
36
  [project.scripts]
38
37
  investfly-cli = "investfly.cli.InvestflyCli:main"
39
38
 
40
39
  [project.urls]
41
- Homepage = "https://www.investfly.com"
40
+ Homepage = "https://www.investfly.com"
41
+
42
+ [tool.setuptools.packages.find]
43
+ include = ["investfly*", "talib*"]
44
+
45
+
@@ -0,0 +1,185 @@
1
+ """
2
+ TA-Lib type stub file for type checking and code completion.
3
+ This provides type hints for TA-Lib functions without implementation.
4
+ """
5
+
6
+ import numpy as np
7
+ from typing import Tuple
8
+
9
+ # Math Operators
10
+ def ADD(real0: np.ndarray, real1: np.ndarray) -> np.ndarray: ...
11
+ def DIV(real0: np.ndarray, real1: np.ndarray) -> np.ndarray: ...
12
+ def MAX(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
13
+ def MAXINDEX(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
14
+ def MIN(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
15
+ def MININDEX(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
16
+ def MINMAX(real: np.ndarray, timeperiod: int = 30) -> Tuple[np.ndarray, np.ndarray]: ...
17
+ def MINMAXINDEX(real: np.ndarray, timeperiod: int = 30) -> Tuple[np.ndarray, np.ndarray]: ...
18
+ def MULT(real0: np.ndarray, real1: np.ndarray) -> np.ndarray: ...
19
+ def SUB(real0: np.ndarray, real1: np.ndarray) -> np.ndarray: ...
20
+ def SUM(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
21
+
22
+ # Math Transform
23
+ def ACOS(real: np.ndarray) -> np.ndarray: ...
24
+ def ASIN(real: np.ndarray) -> np.ndarray: ...
25
+ def ATAN(real: np.ndarray) -> np.ndarray: ...
26
+ def CEIL(real: np.ndarray) -> np.ndarray: ...
27
+ def COS(real: np.ndarray) -> np.ndarray: ...
28
+ def COSH(real: np.ndarray) -> np.ndarray: ...
29
+ def EXP(real: np.ndarray) -> np.ndarray: ...
30
+ def FLOOR(real: np.ndarray) -> np.ndarray: ...
31
+ def LN(real: np.ndarray) -> np.ndarray: ...
32
+ def LOG10(real: np.ndarray) -> np.ndarray: ...
33
+ def SIN(real: np.ndarray) -> np.ndarray: ...
34
+ def SINH(real: np.ndarray) -> np.ndarray: ...
35
+ def SQRT(real: np.ndarray) -> np.ndarray: ...
36
+ def TAN(real: np.ndarray) -> np.ndarray: ...
37
+ def TANH(real: np.ndarray) -> np.ndarray: ...
38
+
39
+ # Overlap Studies
40
+ def BBANDS(real: np.ndarray, timeperiod: int = 5, nbdevup: float = 2.0, nbdevdn: float = 2.0, matype: int = 0) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ...
41
+ def DEMA(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
42
+ def EMA(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
43
+ def HT_TRENDLINE(real: np.ndarray) -> np.ndarray: ...
44
+ def KAMA(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
45
+ def MA(real: np.ndarray, timeperiod: int = 30, matype: int = 0) -> np.ndarray: ...
46
+ def MAMA(real: np.ndarray, fastlimit: float = 0.5, slowlimit: float = 0.05) -> Tuple[np.ndarray, np.ndarray]: ...
47
+ def MAVP(real: np.ndarray, periods: np.ndarray, minperiod: int = 2, maxperiod: int = 30, matype: int = 0) -> np.ndarray: ...
48
+ def MIDPOINT(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
49
+ def MIDPRICE(high: np.ndarray, low: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
50
+ def SAR(high: np.ndarray, low: np.ndarray, acceleration: float = 0.02, maximum: float = 0.2) -> np.ndarray: ...
51
+ def SAREXT(high: np.ndarray, low: np.ndarray, startvalue: float = 0, offsetonreverse: float = 0, accelerationinitlong: float = 0.02, accelerationlong: float = 0.02, accelerationmaxlong: float = 0.2, accelerationinitshort: float = 0.02, accelerationshort: float = 0.02, accelerationmaxshort: float = 0.2) -> np.ndarray: ...
52
+ def SMA(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
53
+ def T3(real: np.ndarray, timeperiod: int = 5, vfactor: float = 0.7) -> np.ndarray: ...
54
+ def TEMA(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
55
+ def TRIMA(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
56
+ def WMA(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
57
+
58
+ # Momentum Indicators
59
+ def ADX(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
60
+ def ADXR(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
61
+ def APO(real: np.ndarray, fastperiod: int = 12, slowperiod: int = 26, matype: int = 0) -> np.ndarray: ...
62
+ def AROON(high: np.ndarray, low: np.ndarray, timeperiod: int = 14) -> Tuple[np.ndarray, np.ndarray]: ...
63
+ def AROONOSC(high: np.ndarray, low: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
64
+ def BOP(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
65
+ def CCI(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
66
+ def CMO(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
67
+ def DX(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
68
+ def MACD(real: np.ndarray, fastperiod: int = 12, slowperiod: int = 26, signalperiod: int = 9) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ...
69
+ def MACDEXT(real: np.ndarray, fastperiod: int = 12, fastmatype: int = 0, slowperiod: int = 26, slowmatype: int = 0, signalperiod: int = 9, signalmatype: int = 0) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ...
70
+ def MACDFIX(real: np.ndarray, signalperiod: int = 9) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: ...
71
+ def MFI(high: np.ndarray, low: np.ndarray, close: np.ndarray, volume: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
72
+ def MINUS_DI(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
73
+ def MINUS_DM(high: np.ndarray, low: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
74
+ def MOM(real: np.ndarray, timeperiod: int = 10) -> np.ndarray: ...
75
+ def PLUS_DI(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
76
+ def PLUS_DM(high: np.ndarray, low: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
77
+ def PPO(real: np.ndarray, fastperiod: int = 12, slowperiod: int = 26, matype: int = 0) -> np.ndarray: ...
78
+ def ROC(real: np.ndarray, timeperiod: int = 10) -> np.ndarray: ...
79
+ def ROCP(real: np.ndarray, timeperiod: int = 10) -> np.ndarray: ...
80
+ def ROCR(real: np.ndarray, timeperiod: int = 10) -> np.ndarray: ...
81
+ def ROCR100(real: np.ndarray, timeperiod: int = 10) -> np.ndarray: ...
82
+ def RSI(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
83
+ def STOCH(high: np.ndarray, low: np.ndarray, close: np.ndarray, fastk_period: int = 5, slowk_period: int = 3, slowk_matype: int = 0, slowd_period: int = 3, slowd_matype: int = 0) -> Tuple[np.ndarray, np.ndarray]: ...
84
+ def STOCHF(high: np.ndarray, low: np.ndarray, close: np.ndarray, fastk_period: int = 5, fastd_period: int = 3, fastd_matype: int = 0) -> Tuple[np.ndarray, np.ndarray]: ...
85
+ def STOCHRSI(real: np.ndarray, timeperiod: int = 14, fastk_period: int = 5, fastd_period: int = 3, fastd_matype: int = 0) -> Tuple[np.ndarray, np.ndarray]: ...
86
+ def TRIX(real: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
87
+ def ULTOSC(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod1: int = 7, timeperiod2: int = 14, timeperiod3: int = 28) -> np.ndarray: ...
88
+ def WILLR(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
89
+
90
+ # Volume Indicators
91
+ def AD(high: np.ndarray, low: np.ndarray, close: np.ndarray, volume: np.ndarray) -> np.ndarray: ...
92
+ def ADOSC(high: np.ndarray, low: np.ndarray, close: np.ndarray, volume: np.ndarray, fastperiod: int = 3, slowperiod: int = 10) -> np.ndarray: ...
93
+ def OBV(close: np.ndarray, volume: np.ndarray) -> np.ndarray: ...
94
+
95
+ # Volatility Indicators
96
+ def ATR(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
97
+ def NATR(high: np.ndarray, low: np.ndarray, close: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
98
+ def TRANGE(high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
99
+
100
+ # Price Transform
101
+ def AVGPRICE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
102
+ def MEDPRICE(high: np.ndarray, low: np.ndarray) -> np.ndarray: ...
103
+ def TYPPRICE(high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
104
+ def WCLPRICE(high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
105
+
106
+ # Cycle Indicators
107
+ def HT_DCPERIOD(real: np.ndarray) -> np.ndarray: ...
108
+ def HT_DCPHASE(real: np.ndarray) -> np.ndarray: ...
109
+ def HT_PHASOR(real: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: ...
110
+ def HT_SINE(real: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: ...
111
+ def HT_TRENDMODE(real: np.ndarray) -> np.ndarray: ...
112
+
113
+ # Pattern Recognition
114
+ def CDL2CROWS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
115
+ def CDL3BLACKCROWS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
116
+ def CDL3INSIDE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
117
+ def CDL3LINESTRIKE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
118
+ def CDL3OUTSIDE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
119
+ def CDL3STARSINSOUTH(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
120
+ def CDL3WHITESOLDIERS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
121
+ def CDLABANDONEDBABY(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray, penetration: float = 0.3) -> np.ndarray: ...
122
+ def CDLADVANCEBLOCK(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
123
+ def CDLBELTHOLD(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
124
+ def CDLBREAKAWAY(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
125
+ def CDLCLOSINGMARUBOZU(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
126
+ def CDLCONCEALBABYSWALL(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
127
+ def CDLCOUNTERATTACK(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
128
+ def CDLDARKCLOUDCOVER(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray, penetration: float = 0.5) -> np.ndarray: ...
129
+ def CDLDOJI(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
130
+ def CDLDOJISTAR(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
131
+ def CDLDRAGONFLYDOJI(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
132
+ def CDLENGULFING(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
133
+ def CDLEVENINGDOJISTAR(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray, penetration: float = 0.3) -> np.ndarray: ...
134
+ def CDLEVENINGSTAR(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray, penetration: float = 0.3) -> np.ndarray: ...
135
+ def CDLGAPSIDESIDEWHITE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
136
+ def CDLGRAVESTONEDOJI(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
137
+ def CDLHAMMER(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
138
+ def CDLHANGINGMAN(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
139
+ def CDLHARAMI(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
140
+ def CDLHARAMICROSS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
141
+ def CDLHIGHWAVE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
142
+ def CDLHIKKAKE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
143
+ def CDLHIKKAKEMOD(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
144
+ def CDLHOMINGPIGEON(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
145
+ def CDLIDENTICAL3CROWS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
146
+ def CDLINNECK(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
147
+ def CDLINVERTEDHAMMER(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
148
+ def CDLKICKING(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
149
+ def CDLKICKINGBYLENGTH(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
150
+ def CDLLADDERBOTTOM(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
151
+ def CDLLONGLEGGEDDOJI(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
152
+ def CDLLONGLINE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
153
+ def CDLMARUBOZU(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
154
+ def CDLMATCHINGLOW(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
155
+ def CDLMATHOLD(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray, penetration: float = 0.5) -> np.ndarray: ...
156
+ def CDLMORNINGDOJISTAR(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray, penetration: float = 0.3) -> np.ndarray: ...
157
+ def CDLMORNINGSTAR(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray, penetration: float = 0.3) -> np.ndarray: ...
158
+ def CDLONNECK(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
159
+ def CDLPIERCING(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
160
+ def CDLRICKSHAWMAN(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
161
+ def CDLRISEFALL3METHODS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
162
+ def CDLSEPARATINGLINES(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
163
+ def CDLSHOOTINGSTAR(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
164
+ def CDLSHORTLINE(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
165
+ def CDLSPINNINGTOP(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
166
+ def CDLSTALLEDPATTERN(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
167
+ def CDLSTICKSANDWICH(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
168
+ def CDLTAKURI(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
169
+ def CDLTASUKIGAP(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
170
+ def CDLTHRUSTING(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
171
+ def CDLTRISTAR(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
172
+ def CDLUNIQUE3RIVER(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
173
+ def CDLUPSIDEGAP2CROWS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
174
+ def CDLXSIDEGAP3METHODS(open: np.ndarray, high: np.ndarray, low: np.ndarray, close: np.ndarray) -> np.ndarray: ...
175
+
176
+ # Statistic Functions
177
+ def BETA(real0: np.ndarray, real1: np.ndarray, timeperiod: int = 5) -> np.ndarray: ...
178
+ def CORREL(real0: np.ndarray, real1: np.ndarray, timeperiod: int = 30) -> np.ndarray: ...
179
+ def LINEARREG(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
180
+ def LINEARREG_ANGLE(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
181
+ def LINEARREG_INTERCEPT(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
182
+ def LINEARREG_SLOPE(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
183
+ def STDDEV(real: np.ndarray, timeperiod: int = 5, nbdev: float = 1.0) -> np.ndarray: ...
184
+ def TSF(real: np.ndarray, timeperiod: int = 14) -> np.ndarray: ...
185
+ def VAR(real: np.ndarray, timeperiod: int = 5, nbdev: float = 1.0) -> np.ndarray: ...
File without changes
File without changes