From efc2c8b625f82ec16ddf6b08f10492039dd4240a Mon Sep 17 00:00:00 2001 From: begood Date: Fri, 11 Aug 2023 09:26:51 +0200 Subject: [PATCH] TVSCREENER-27 Generate field values --- .github/workflows/codecov.yml | 46 +- .github/workflows/pip-publish.yml | 34 +- README.md | 14 +- generate/Generate FilterFields.ipynb | 175 +++++ generate/code/country.py.generated | 88 +++ generate/code/exchange.py.generated | 14 + generate/code/index.py.generated | 53 ++ generate/code/industry.py.generated | 140 ++++ generate/code/sector.py.generated | 31 + generate/code/submarket.py.generated | 13 + generate/code/symbol_type.py.generated | 21 + generate/crypto.json | 1 - generate/data/country.json | 83 +++ generate/data/crypto.json | 732 +++++++++++++++++++ generate/data/exchange.json | 9 + generate/{ => data}/forex.json | 0 generate/data/index.json | 48 ++ generate/data/industry.json | 135 ++++ generate/data/main.json | 11 + generate/data/patterns.json | 31 + generate/data/sector.json | 26 + generate/{ => data}/stock.json | 0 generate/data/submarket.json | 8 + generate/data/symbol type.json | 16 + generate/data/time_intervals.json | 129 ++++ generate/generate.py | 131 +++- generate/main.json | 2 - generate/patterns.json | 29 - generate/time_intervals.json | 129 ---- test/functional/test_forexscreener.py | 3 +- test/functional/test_stockscreener.py | 19 +- test/unit/test_fields.py | 3 +- test/unit/test_filters.py | 21 +- tvscreener/__init__.py | 13 +- tvscreener/{beauty/__init__.py => beauty.py} | 0 tvscreener/field/__init__.py | 470 +++++++++++- tvscreener/field/crypto.py | 7 +- tvscreener/field/forex.py | 7 +- tvscreener/field/stock.py | 7 +- tvscreener/filter.py | 43 ++ tvscreener/filter/__init__.py | 308 -------- 41 files changed, 2461 insertions(+), 589 deletions(-) create mode 100644 generate/Generate FilterFields.ipynb create mode 100644 generate/code/country.py.generated create mode 100644 generate/code/exchange.py.generated create mode 100644 generate/code/index.py.generated create mode 100644 generate/code/industry.py.generated create mode 100644 generate/code/sector.py.generated create mode 100644 generate/code/submarket.py.generated create mode 100644 generate/code/symbol_type.py.generated delete mode 100644 generate/crypto.json create mode 100644 generate/data/country.json create mode 100644 generate/data/crypto.json create mode 100644 generate/data/exchange.json rename generate/{ => data}/forex.json (100%) create mode 100644 generate/data/index.json create mode 100644 generate/data/industry.json create mode 100644 generate/data/main.json create mode 100644 generate/data/patterns.json create mode 100644 generate/data/sector.json rename generate/{ => data}/stock.json (100%) create mode 100644 generate/data/submarket.json create mode 100644 generate/data/symbol type.json create mode 100644 generate/data/time_intervals.json delete mode 100644 generate/main.json delete mode 100644 generate/patterns.json delete mode 100644 generate/time_intervals.json rename tvscreener/{beauty/__init__.py => beauty.py} (100%) create mode 100644 tvscreener/filter.py delete mode 100644 tvscreener/filter/__init__.py diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index b1f7f53..1db0410 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -2,32 +2,32 @@ name: Codecov on: pull_request: - branches: + branches: - master jobs: run: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - name: Setup Python - uses: actions/setup-python@master - with: - python-version: '3.x' - - name: Generate coverage report - run: | - pip install -r requirements.txt - pip install pytest - pip install pytest-cov - pytest --cov=./ --cov-report=xml - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - with: - token: ${{ secrets.CODECOV_TOKEN }} - #directory: ./coverage/reports/ - env_vars: OS,PYTHON - fail_ci_if_error: true - files: ./coverage.xml - flags: unittests - name: codecov-umbrella - verbose: true \ No newline at end of file + - uses: actions/checkout@master + - name: Setup Python + uses: actions/setup-python@master + with: + python-version: '3.x' + - name: Generate coverage report + run: | + pip install -r requirements.txt + pip install pytest + pip install pytest-cov + pytest --cov=./ --cov-report=xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + #directory: ./coverage/reports/ + env_vars: OS,PYTHON + fail_ci_if_error: true + files: ./coverage.xml + flags: unittests + name: codecov-umbrella + verbose: true \ No newline at end of file diff --git a/.github/workflows/pip-publish.yml b/.github/workflows/pip-publish.yml index bdaab28..4ba9ac4 100644 --- a/.github/workflows/pip-publish.yml +++ b/.github/workflows/pip-publish.yml @@ -10,7 +10,7 @@ name: Upload Python Package on: release: - types: [published] + types: [ published ] permissions: contents: read @@ -21,19 +21,19 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build - - name: Build package - run: python -m build - - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/README.md b/README.md index 5be8849..dba0fa6 100644 --- a/README.md +++ b/README.md @@ -16,24 +16,28 @@ Get the results as a Pandas Dataframe ![dataframe.png](https://github.com/houseofai/tvscreener/blob/main/.github/img/dataframe.png?raw=true) # Main Features + - Query **Stock**, **Forex** and **Crypto** Screener - All the **fields available**: ~300 fields - even hidden ones) - **Any time interval** (`no need to be a registered user` - 1D, 5m, 1h, etc.) - Filters by any fields, symbols, markets, countries, etc. - Get the results as a Pandas Dataframe - ## Installation + The source code is currently hosted on GitHub at: https://github.com/houseofai/tvscreener Binary installers for the latest released version are available at the [Python Package Index (PyPI)](https://pypi.org/project/tvscreener) + ```sh # or PyPI pip install tvscreener ``` + From pip + GitHub: + ```sh $ pip install git+https://github.com/houseofai/tradingview-screener@main ``` @@ -41,6 +45,7 @@ $ pip install git+https://github.com/houseofai/tradingview-screener@main ## Usage For Stocks screener: + ```python import tvscreener as tvs @@ -49,14 +54,18 @@ df = ss.get() # ... returns a dataframe with 150 rows by default ``` + For Forex screener: + ```python import tvscreener as tvs fs = tvs.ForexScreener() df = fs.get() ``` + For Crypto screener: + ```python import tvscreener as tvs @@ -66,4 +75,5 @@ df = cs.get() ## Parameters -For Options and Filters, please check the [notebooks](https://github.com/houseofai/tvscreener/tree/main/notebooks) for examples. \ No newline at end of file +For Options and Filters, please check the [notebooks](https://github.com/houseofai/tvscreener/tree/main/notebooks) for +examples. \ No newline at end of file diff --git a/generate/Generate FilterFields.ipynb b/generate/Generate FilterFields.ipynb new file mode 100644 index 0000000..74885c3 --- /dev/null +++ b/generate/Generate FilterFields.ipynb @@ -0,0 +1,175 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "initial_id", + "metadata": { + "collapsed": true, + "ExecuteTime": { + "end_time": "2023-08-11T06:52:01.213849587Z", + "start_time": "2023-08-11T06:52:01.172112997Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], + "source": [ + "from generate import scrap_field_values\n", + "import json\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "outputs": [], + "source": [ + "from generate import fill_filter_template, generate_filter_columns\n", + "from generate import write\n", + "\n", + "\n", + "def save_columns(url):\n", + " fields_dict = scrap_field_values(url)\n", + " for key, value in fields_dict.items():\n", + " with open(f'data/{key.lower()}.json', 'w') as f:\n", + " json.dump({key: value}, f)\n", + " return fields_dict\n", + " \n", + "def generate_code_files(name):\n", + " with open(f'data/{name.lower()}.json') as f:\n", + " filters_ = json.load(f)\n", + " formatted_columns = generate_filter_columns(filters_[name])\n", + " template = fill_filter_template(name.replace(' ', ''), formatted_columns)\n", + " write(name.replace(' ', '_').lower(), template)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-11T06:52:03.190052866Z", + "start_time": "2023-08-11T06:52:03.186114291Z" + } + }, + "id": "d4c4d0ddb0c0119b" + }, + { + "cell_type": "code", + "execution_count": 4, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[1]/div[1] ...\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[2]/div[1] ...\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[3]/div[1] ...\n", + "TimeoutException on field: Primary Listing\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[4]/div[1] ...\n", + "TimeoutException on field: Current trading day\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[5]/div[1] ...\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[6]/div[1] ...\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[7]/div[1] ...\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[8]/div[1] ...\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[9]/div[1] ...\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[10]/div[1] ...\n", + "NoSuchElementException on field: Market Capitalization\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[11]/div[1] ...\n", + "NoSuchElementException on field: Volume\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[12]/div[1] ...\n", + "NoSuchElementException on field: Average Volume (10 day)\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[13]/div[1] ...\n", + "NoSuchElementException on field: Average Volume (30 day)\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[14]/div[1] ...\n", + "NoSuchElementException on field: Average Volume (60 day)\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[15]/div[1] ...\n", + "NoSuchElementException on field: Average Volume (90 day)\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[16]/div[1] ...\n", + "TimeoutException on field: Relative Volume\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[17]/div[1] ...\n", + "TimeoutException on field: Relative Volume at Time\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[18]/div[1] ...\n", + "TimeoutException on field: Change %\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[19]/div[1] ...\n", + "TimeoutException on field: Change 1m, %\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[20]/div[1] ...\n", + "TimeoutException on field: Change 5m, %\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[21]/div[1] ...\n", + "TimeoutException on field: Change 15m, %\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[22]/div[1] ...\n", + "TimeoutException on field: Change 1h, %\n", + "Search field on xpath: /html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[23]/div[1] ...\n" + ] + } + ], + "source": [ + "stock_url = \"https://www.tradingview.com/screener/\"\n", + "filters = save_columns(stock_url)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-11T06:52:42.294915919Z", + "start_time": "2023-08-11T06:52:04.108834356Z" + } + }, + "id": "e4eabbd29fc14556" + }, + { + "cell_type": "code", + "execution_count": 7, + "outputs": [], + "source": [ + "for key in filters.keys():\n", + " generate_code_files(key)" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-08-11T07:05:13.158804479Z", + "start_time": "2023-08-11T07:05:13.148339900Z" + } + }, + "id": "fce7ec0c7477cb3c" + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [], + "metadata": { + "collapsed": false + }, + "id": "c8b265fdafe0ea0" + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/generate/code/country.py.generated b/generate/code/country.py.generated new file mode 100644 index 0000000..1666c73 --- /dev/null +++ b/generate/code/country.py.generated @@ -0,0 +1,88 @@ + +# ---------------------- +# Generated file +# 2023-08-11 07:05:13.156337 +# ---------------------- +from enum import Enum + + +class Country(Enum): + ALBANIA = 'Albania' + ARGENTINA = 'Argentina' + AUSTRALIA = 'Australia' + AUSTRIA = 'Austria' + AZERBAIJAN = 'Azerbaijan' + BAHAMAS = 'Bahamas' + BARBADOS = 'Barbados' + BELGIUM = 'Belgium' + BERMUDA = 'Bermuda' + BRAZIL = 'Brazil' + BRITISH_VIRGIN_ISLANDS = 'British Virgin Islands' + CAMBODIA = 'Cambodia' + CANADA = 'Canada' + CAYMAN_ISLANDS = 'Cayman Islands' + CHILE = 'Chile' + CHINA = 'China' + COLOMBIA = 'Colombia' + COSTA_RICA = 'Costa Rica' + CYPRUS = 'Cyprus' + CZECH_REPUBLIC = 'Czech Republic' + DENMARK = 'Denmark' + DOMINICAN_REPUBLIC = 'Dominican Republic' + EGYPT = 'Egypt' + FAROE_ISLANDS = 'Faroe Islands' + FINLAND = 'Finland' + FRANCE = 'France' + GERMANY = 'Germany' + GIBRALTAR = 'Gibraltar' + GREECE = 'Greece' + HONG_KONG = 'Hong Kong' + HUNGARY = 'Hungary' + ICELAND = 'Iceland' + INDIA = 'India' + INDONESIA = 'Indonesia' + IRELAND = 'Ireland' + ISRAEL = 'Israel' + ITALY = 'Italy' + JAMAICA = 'Jamaica' + JAPAN = 'Japan' + JORDAN = 'Jordan' + KAZAKHSTAN = 'Kazakhstan' + LUXEMBOURG = 'Luxembourg' + MACAU = 'Macau' + MACEDONIA = 'Macedonia' + MALAYSIA = 'Malaysia' + MALTA = 'Malta' + MAURITIUS = 'Mauritius' + MEXICO = 'Mexico' + MONACO = 'Monaco' + MONGOLIA = 'Mongolia' + MONTENEGRO = 'Montenegro' + NETHERLANDS = 'Netherlands' + NEW_ZEALAND = 'New Zealand' + NORWAY = 'Norway' + PANAMA = 'Panama' + PERU = 'Peru' + PHILIPPINES = 'Philippines' + POLAND = 'Poland' + PORTUGAL = 'Portugal' + PUERTO_RICO = 'Puerto Rico' + ROMANIA = 'Romania' + RUSSIAN_FEDERATION = 'Russian Federation' + SINGAPORE = 'Singapore' + SOUTH_AFRICA = 'South Africa' + SOUTH_KOREA = 'South Korea' + SPAIN = 'Spain' + SWEDEN = 'Sweden' + SWITZERLAND = 'Switzerland' + TAIWAN = 'Taiwan' + TANZANIA = 'Tanzania' + THAILAND = 'Thailand' + TURKEY = 'Turkey' + U_S__VIRGIN_ISLANDS = 'U.S. Virgin Islands' + UNITED_ARAB_EMIRATES = 'United Arab Emirates' + UNITED_KINGDOM = 'United Kingdom' + UNITED_STATES = 'United States' + URUGUAY = 'Uruguay' + VIETNAM = 'Vietnam' + \ No newline at end of file diff --git a/generate/code/exchange.py.generated b/generate/code/exchange.py.generated new file mode 100644 index 0000000..4a0eecb --- /dev/null +++ b/generate/code/exchange.py.generated @@ -0,0 +1,14 @@ + +# ---------------------- +# Generated file +# 2023-08-11 07:05:13.153328 +# ---------------------- +from enum import Enum + + +class Exchange(Enum): + NYSE_ARCA = 'NYSE ARCA' + NASDAQ = 'NASDAQ' + NYSE = 'NYSE' + OTC = 'OTC' + \ No newline at end of file diff --git a/generate/code/index.py.generated b/generate/code/index.py.generated new file mode 100644 index 0000000..d48324b --- /dev/null +++ b/generate/code/index.py.generated @@ -0,0 +1,53 @@ + +# ---------------------- +# Generated file +# 2023-08-11 07:05:13.155095 +# ---------------------- +from enum import Enum + + +class Index(Enum): + DOW_JONES_COMPOSITE_AVERAGE = 'Dow Jones Composite Average' + DOW_JONES_INDUSTRIAL_AVERAGE = 'Dow Jones Industrial Average' + DOW_JONES_TRANSPORTATION_AVERAGE = 'Dow Jones Transportation Average' + DOW_JONES_UTILITY_AVERAGE = 'Dow Jones Utility Average' + KBW_NASDAQ_BANK_INDEX = 'KBW NASDAQ BANK INDEX' + MINI_RUSSELL_2000_INDEX = 'MINI RUSSELL 2000 INDEX' + NASDAQ_100 = 'NASDAQ 100' + NASDAQ_100_TECHNOLOGY_SECTOR = 'NASDAQ 100 TECHNOLOGY SECTOR' + NASDAQ_BANK = 'NASDAQ BANK' + NASDAQ_BIOTECHNOLOGY = 'NASDAQ BIOTECHNOLOGY' + NASDAQ_COMPOSITE = 'NASDAQ COMPOSITE' + NASDAQ_COMPUTER = 'NASDAQ COMPUTER' + NASDAQ_GOLDEN_DRAGON_CHINA_INDEX = 'NASDAQ GOLDEN DRAGON CHINA INDEX' + NASDAQ_INDUSTRIAL = 'NASDAQ INDUSTRIAL' + NASDAQ_INSURANCE = 'NASDAQ INSURANCE' + NASDAQ_OTHER_FINANCE = 'NASDAQ OTHER FINANCE' + NASDAQ_TELECOMMUNICATIONS = 'NASDAQ TELECOMMUNICATIONS' + NASDAQ_TRANSPORTATION = 'NASDAQ TRANSPORTATION' + NASDAQ_US_BENCHMARK_FOOD_PRODUCERS_INDEX = 'NASDAQ US BENCHMARK FOOD PRODUCERS INDEX' + NYSE_ARCA_MAJOR_MARKET = 'NYSE ARCA MAJOR MARKET' + PHLX_GOLD_AND_SILVER_SECTOR_INDEX = 'PHLX GOLD AND SILVER SECTOR INDEX' + PHLX_HOUSING_SECTOR = 'PHLX HOUSING SECTOR' + PHLX_OIL_SERVICE_SECTOR = 'PHLX OIL SERVICE SECTOR' + PHLX_SEMICONDUCTOR = 'PHLX SEMICONDUCTOR' + PHLX_UTILITY_SECTOR = 'PHLX UTILITY SECTOR' + RUSSELL_1000 = 'RUSSELL 1000' + RUSSELL_2000 = 'RUSSELL 2000' + RUSSELL_3000 = 'RUSSELL 3000' + SANDP_100 = 'S&P 100' + SANDP_400 = 'S&P 400' + SANDP_500 = 'S&P 500' + SANDP_500_COMMUNICATION_SERVICES = 'S&P 500 Communication Services' + SANDP_500_CONSUMER_DISCRETIONARY = 'S&P 500 Consumer Discretionary' + SANDP_500_CONSUMER_STAPLES = 'S&P 500 Consumer Staples' + SANDP_500_ESG_INDEX = 'S&P 500 ESG INDEX' + SANDP_500_ENERGY = 'S&P 500 Energy' + SANDP_500_FINANCIALS = 'S&P 500 Financials' + SANDP_500_HEALTH_CARE = 'S&P 500 Health Care' + SANDP_500_INDUSTRIALS = 'S&P 500 Industrials' + SANDP_500_INFORMATION_TECHNOLOGY = 'S&P 500 Information Technology' + SANDP_500_MATERIALS = 'S&P 500 Materials' + SANDP_500_REAL_ESTATE = 'S&P 500 Real Estate' + SANDP_500_UTILITIES = 'S&P 500 Utilities' + \ No newline at end of file diff --git a/generate/code/industry.py.generated b/generate/code/industry.py.generated new file mode 100644 index 0000000..c3099c5 --- /dev/null +++ b/generate/code/industry.py.generated @@ -0,0 +1,140 @@ + +# ---------------------- +# Generated file +# 2023-08-11 07:05:13.155735 +# ---------------------- +from enum import Enum + + +class Industry(Enum): + ADVERTISINGMARKETING_SERVICES = 'Advertising/Marketing Services' + AEROSPACE_AND_DEFENSE = 'Aerospace & Defense' + AGRICULTURAL_COMMODITIESMILLING = 'Agricultural Commodities/Milling' + AIR_FREIGHTCOURIERS = 'Air Freight/Couriers' + AIRLINES = 'Airlines' + ALTERNATIVE_POWER_GENERATION = 'Alternative Power Generation' + ALUMINUM = 'Aluminum' + APPARELFOOTWEAR = 'Apparel/Footwear' + APPARELFOOTWEAR_RETAIL = 'Apparel/Footwear Retail' + AUTO_PARTS_OEM = 'Auto Parts: OEM' + AUTOMOTIVE_AFTERMARKET = 'Automotive Aftermarket' + BEVERAGES_ALCOHOLIC = 'Beverages: Alcoholic' + BEVERAGES_NONALCOHOLIC = 'Beverages: Non-Alcoholic' + BIOTECHNOLOGY = 'Biotechnology' + BROADCASTING = 'Broadcasting' + BUILDING_PRODUCTS = 'Building Products' + CABLESATELLITE_TV = 'Cable/Satellite TV' + CASINOSGAMING = 'Casinos/Gaming' + CATALOGSPECIALTY_DISTRIBUTION = 'Catalog/Specialty Distribution' + CHEMICALS_AGRICULTURAL = 'Chemicals: Agricultural' + CHEMICALS_MAJOR_DIVERSIFIED = 'Chemicals: Major Diversified' + CHEMICALS_SPECIALTY = 'Chemicals: Specialty' + COAL = 'Coal' + COMMERCIAL_PRINTINGFORMS = 'Commercial Printing/Forms' + COMPUTER_COMMUNICATIONS = 'Computer Communications' + COMPUTER_PERIPHERALS = 'Computer Peripherals' + COMPUTER_PROCESSING_HARDWARE = 'Computer Processing Hardware' + CONSTRUCTION_MATERIALS = 'Construction Materials' + CONSUMER_SUNDRIES = 'Consumer Sundries' + CONTAINERSPACKAGING = 'Containers/Packaging' + CONTRACT_DRILLING = 'Contract Drilling' + DATA_PROCESSING_SERVICES = 'Data Processing Services' + DEPARTMENT_STORES = 'Department Stores' + DISCOUNT_STORES = 'Discount Stores' + DRUGSTORE_CHAINS = 'Drugstore Chains' + ELECTRIC_UTILITIES = 'Electric Utilities' + ELECTRICAL_PRODUCTS = 'Electrical Products' + ELECTRONIC_COMPONENTS = 'Electronic Components' + ELECTRONIC_EQUIPMENTINSTRUMENTS = 'Electronic Equipment/Instruments' + ELECTRONIC_PRODUCTION_EQUIPMENT = 'Electronic Production Equipment' + ELECTRONICS_DISTRIBUTORS = 'Electronics Distributors' + ELECTRONICSAPPLIANCE_STORES = 'Electronics/Appliance Stores' + ELECTRONICSAPPLIANCES = 'Electronics/Appliances' + ENGINEERING_AND_CONSTRUCTION = 'Engineering & Construction' + ENVIRONMENTAL_SERVICES = 'Environmental Services' + FINANCERENTALLEASING = 'Finance/Rental/Leasing' + FINANCIAL_CONGLOMERATES = 'Financial Conglomerates' + FINANCIAL_PUBLISHINGSERVICES = 'Financial Publishing/Services' + FOOD_DISTRIBUTORS = 'Food Distributors' + FOOD_RETAIL = 'Food Retail' + FOOD_MAJOR_DIVERSIFIED = 'Food: Major Diversified' + FOOD_MEATFISHDAIRY = 'Food: Meat/Fish/Dairy' + FOOD_SPECIALTYCANDY = 'Food: Specialty/Candy' + FOREST_PRODUCTS = 'Forest Products' + GAS_DISTRIBUTORS = 'Gas Distributors' + GENERAL_GOVERNMENT = 'General Government' + HOME_FURNISHINGS = 'Home Furnishings' + HOME_IMPROVEMENT_CHAINS = 'Home Improvement Chains' + HOMEBUILDING = 'Homebuilding' + HOSPITALNURSING_MANAGEMENT = 'Hospital/Nursing Management' + HOTELSRESORTSCRUISE_LINES = 'Hotels/Resorts/Cruise lines' + HOUSEHOLDPERSONAL_CARE = 'Household/Personal Care' + INDUSTRIAL_CONGLOMERATES = 'Industrial Conglomerates' + INDUSTRIAL_MACHINERY = 'Industrial Machinery' + INDUSTRIAL_SPECIALTIES = 'Industrial Specialties' + INFORMATION_TECHNOLOGY_SERVICES = 'Information Technology Services' + INSURANCE_BROKERSSERVICES = 'Insurance Brokers/Services' + INTEGRATED_OIL = 'Integrated Oil' + INTERNET_RETAIL = 'Internet Retail' + INTERNET_SOFTWARESERVICES = 'Internet Software/Services' + INVESTMENT_BANKSBROKERS = 'Investment Banks/Brokers' + INVESTMENT_MANAGERS = 'Investment Managers' + INVESTMENT_TRUSTSMUTUAL_FUNDS = 'Investment Trusts/Mutual Funds' + LIFEHEALTH_INSURANCE = 'Life/Health Insurance' + MAJOR_BANKS = 'Major Banks' + MAJOR_TELECOMMUNICATIONS = 'Major Telecommunications' + MANAGED_HEALTH_CARE = 'Managed Health Care' + MARINE_SHIPPING = 'Marine Shipping' + MEDIA_CONGLOMERATES = 'Media Conglomerates' + MEDICAL_DISTRIBUTORS = 'Medical Distributors' + MEDICAL_SPECIALTIES = 'Medical Specialties' + MEDICALNURSING_SERVICES = 'Medical/Nursing Services' + METAL_FABRICATION = 'Metal Fabrication' + MISCELLANEOUS = 'Miscellaneous' + MISCELLANEOUS_COMMERCIAL_SERVICES = 'Miscellaneous Commercial Services' + MISCELLANEOUS_MANUFACTURING = 'Miscellaneous Manufacturing' + MOTOR_VEHICLES = 'Motor Vehicles' + MOVIESENTERTAINMENT = 'Movies/Entertainment' + MULTILINE_INSURANCE = 'Multi-Line Insurance' + OFFICE_EQUIPMENTSUPPLIES = 'Office Equipment/Supplies' + OIL_AND_GAS_PIPELINES = 'Oil & Gas Pipelines' + OIL_AND_GAS_PRODUCTION = 'Oil & Gas Production' + OIL_REFININGMARKETING = 'Oil Refining/Marketing' + OILFIELD_SERVICESEQUIPMENT = 'Oilfield Services/Equipment' + OTHER_CONSUMER_SERVICES = 'Other Consumer Services' + OTHER_CONSUMER_SPECIALTIES = 'Other Consumer Specialties' + OTHER_METALSMINERALS = 'Other Metals/Minerals' + OTHER_TRANSPORTATION = 'Other Transportation' + PACKAGED_SOFTWARE = 'Packaged Software' + PERSONNEL_SERVICES = 'Personnel Services' + PHARMACEUTICALS_GENERIC = 'Pharmaceuticals: Generic' + PHARMACEUTICALS_MAJOR = 'Pharmaceuticals: Major' + PHARMACEUTICALS_OTHER = 'Pharmaceuticals: Other' + PRECIOUS_METALS = 'Precious Metals' + PROPERTYCASUALTY_INSURANCE = 'Property/Casualty Insurance' + PUBLISHING_BOOKSMAGAZINES = 'Publishing: Books/Magazines' + PUBLISHING_NEWSPAPERS = 'Publishing: Newspapers' + PULP_AND_PAPER = 'Pulp & Paper' + RAILROADS = 'Railroads' + REAL_ESTATE_DEVELOPMENT = 'Real Estate Development' + REAL_ESTATE_INVESTMENT_TRUSTS = 'Real Estate Investment Trusts' + RECREATIONAL_PRODUCTS = 'Recreational Products' + REGIONAL_BANKS = 'Regional Banks' + RESTAURANTS = 'Restaurants' + SAVINGS_BANKS = 'Savings Banks' + SEMICONDUCTORS = 'Semiconductors' + SERVICES_TO_THE_HEALTH_INDUSTRY = 'Services to the Health Industry' + SPECIALTY_INSURANCE = 'Specialty Insurance' + SPECIALTY_STORES = 'Specialty Stores' + SPECIALTY_TELECOMMUNICATIONS = 'Specialty Telecommunications' + STEEL = 'Steel' + TELECOMMUNICATIONS_EQUIPMENT = 'Telecommunications Equipment' + TEXTILES = 'Textiles' + TOBACCO = 'Tobacco' + TOOLS_AND_HARDWARE = 'Tools & Hardware' + TRUCKING = 'Trucking' + TRUCKSCONSTRUCTIONFARM_MACHINERY = 'Trucks/Construction/Farm Machinery' + WATER_UTILITIES = 'Water Utilities' + WHOLESALE_DISTRIBUTORS = 'Wholesale Distributors' + WIRELESS_TELECOMMUNICATIONS = 'Wireless Telecommunications' + \ No newline at end of file diff --git a/generate/code/sector.py.generated b/generate/code/sector.py.generated new file mode 100644 index 0000000..db24cb1 --- /dev/null +++ b/generate/code/sector.py.generated @@ -0,0 +1,31 @@ + +# ---------------------- +# Generated file +# 2023-08-11 07:05:13.154481 +# ---------------------- +from enum import Enum + + +class Sector(Enum): + COMMERCIAL_SERVICES = 'Commercial Services' + COMMUNICATIONS = 'Communications' + CONSUMER_DURABLES = 'Consumer Durables' + CONSUMER_NONDURABLES = 'Consumer Non-Durables' + CONSUMER_SERVICES = 'Consumer Services' + DISTRIBUTION_SERVICES = 'Distribution Services' + ELECTRONIC_TECHNOLOGY = 'Electronic Technology' + ENERGY_MINERALS = 'Energy Minerals' + FINANCE = 'Finance' + GOVERNMENT = 'Government' + HEALTH_SERVICES = 'Health Services' + HEALTH_TECHNOLOGY = 'Health Technology' + INDUSTRIAL_SERVICES = 'Industrial Services' + MISCELLANEOUS = 'Miscellaneous' + NONENERGY_MINERALS = 'Non-Energy Minerals' + PROCESS_INDUSTRIES = 'Process Industries' + PRODUCER_MANUFACTURING = 'Producer Manufacturing' + RETAIL_TRADE = 'Retail Trade' + TECHNOLOGY_SERVICES = 'Technology Services' + TRANSPORTATION = 'Transportation' + UTILITIES = 'Utilities' + \ No newline at end of file diff --git a/generate/code/submarket.py.generated b/generate/code/submarket.py.generated new file mode 100644 index 0000000..b5d93b3 --- /dev/null +++ b/generate/code/submarket.py.generated @@ -0,0 +1,13 @@ + +# ---------------------- +# Generated file +# 2023-08-11 07:05:13.153890 +# ---------------------- +from enum import Enum + + +class Submarket(Enum): + OTCQB = 'OTCQB' + OTCQX = 'OTCQX' + PINK = 'PINK' + \ No newline at end of file diff --git a/generate/code/symbol_type.py.generated b/generate/code/symbol_type.py.generated new file mode 100644 index 0000000..c52454c --- /dev/null +++ b/generate/code/symbol_type.py.generated @@ -0,0 +1,21 @@ + +# ---------------------- +# Generated file +# 2023-08-11 07:05:13.152605 +# ---------------------- +from enum import Enum + + +class SymbolType(Enum): + CLOSEDEND_FUND = 'Closed-end fund' + COMMON_STOCK = 'Common Stock' + DEPOSITARY_RECEIPT = 'Depositary Receipt' + ETF = 'ETF' + ETN = 'ETN' + MUTUAL_FUND = 'Mutual fund' + PREFERRED_STOCK = 'Preferred Stock' + REIT = 'REIT' + STRUCTURED = 'Structured' + TRUST_FUND = 'Trust fund' + UIT = 'UIT' + \ No newline at end of file diff --git a/generate/crypto.json b/generate/crypto.json deleted file mode 100644 index 6480d31..0000000 --- a/generate/crypto.json +++ /dev/null @@ -1 +0,0 @@ -{"change": {"label": "Change %", "format": "percent", "historical": false}, "change_abs": {"label": "Change", "format": "float", "historical": false}, "exchange": {"label": "Exchange", "format": "text", "historical": false}, "high": {"label": "High", "format": "float", "historical": false}, "low": {"label": "Low", "format": "float", "historical": false}, "close": {"label": "Price", "format": "float", "historical": false}, "Recommend.All": {"label": "Technical Rating", "format": "rating", "historical": false}, "volume": {"label": "Volume", "format": "number_group", "historical": false}, "24h_vol_change|5": {"label": "Volume 24h Change %", "format": "percent", "historical": false}, "24h_vol|5": {"label": "Volume 24h in USD", "format": "number_group", "historical": false}, "High.1M": {"label": "1-Month High", "format": "round", "historical": false}, "Low.1M": {"label": "1-Month Low", "format": "round", "historical": false}, "High.3M": {"label": "3-Month High", "format": "round", "historical": false}, "Low.3M": {"label": "3-Month Low", "format": "round", "historical": false}, "Perf.3M": {"label": "3-Month Performance", "format": "percent", "historical": false}, "Perf.5Y": {"label": "5Y Performance", "format": "percent", "historical": false}, "High.6M": {"label": "6-Month High", "format": "round", "historical": false}, "Low.6M": {"label": "6-Month Low", "format": "round", "historical": false}, "Perf.6M": {"label": "6-Month Performance", "format": "percent", "historical": false}, "price_52_week_high": {"label": "52 Week High", "format": "round", "historical": false}, "price_52_week_low": {"label": "52 Week Low", "format": "round", "historical": false}, "High.All": {"label": "All Time High", "format": "round", "historical": false}, "Low.All": {"label": "All Time Low", "format": "round", "historical": false}, "Perf.All": {"label": "All Time Performance", "format": "percent", "historical": false}, "Aroon.Down": {"label": "Aroon Down (14)", "format": "round", "historical": false}, "Aroon.Up": {"label": "Aroon Up (14)", "format": "round", "historical": false}, "ask": {"label": "Ask", "format": "float", "historical": false}, "total_shares_outstanding": {"label": "Available Coins", "format": "missing", "historical": false}, "ADR": {"label": "Average Day Range (14)", "format": "float", "historical": false}, "ADX": {"label": "Average Directional Index (14)", "format": "computed_recommendation", "historical": false}, "ATR": {"label": "Average True Range (14)", "format": "float", "historical": false}, "average_volume_10d_calc": {"label": "Average Volume (10 day)", "format": "number_group", "historical": false}, "average_volume_30d_calc": {"label": "Average Volume (30 day)", "format": "number_group", "historical": false}, "average_volume_60d_calc": {"label": "Average Volume (60 day)", "format": "number_group", "historical": false}, "average_volume_90d_calc": {"label": "Average Volume (90 day)", "format": "number_group", "historical": false}, "AO": {"label": "Awesome Oscillator", "format": "computed_recommendation", "historical": true}, "bid": {"label": "Bid", "format": "float", "historical": false}, "BB.lower": {"label": "Bollinger Lower Band (20)", "format": "computed_recommendation", "historical": false}, "BB.upper": {"label": "Bollinger Upper Band (20)", "format": "computed_recommendation", "historical": false}, "BBPower": {"label": "Bull Bear Power", "format": "recommendation", "historical": false}, "change.60": {"label": "Change 1h, %", "format": "percent", "historical": false}, "change_abs.60": {"label": "Change 1h", "format": "round", "historical": false}, "change.1": {"label": "Change 1m, %", "format": "percent", "historical": false}, "change_abs.1": {"label": "Change 1m", "format": "round", "historical": false}, "change.1M": {"label": "Change 1M, %", "format": "percent", "historical": false}, "change_abs.1M": {"label": "Change 1M", "format": "round", "historical": false}, "change.1W": {"label": "Change 1W, %", "format": "percent", "historical": false}, "change_abs.1W": {"label": "Change 1W", "format": "round", "historical": false}, "change.240": {"label": "Change 4h, %", "format": "percent", "historical": false}, "change_abs.240": {"label": "Change 4h", "format": "round", "historical": false}, "change.5": {"label": "Change 5m, %", "format": "percent", "historical": false}, "change_abs.5": {"label": "Change 5m", "format": "round", "historical": false}, "change.15": {"label": "Change 15m, %", "format": "percent", "historical": false}, "change_abs.15": {"label": "Change 15m", "format": "round", "historical": false}, "change_from_open": {"label": "Change from Open %", "format": "percent", "historical": false}, "change_from_open_abs": {"label": "Change from Open", "format": "float", "historical": false}, "CCI20": {"label": "Commodity Channel Index (20)", "format": "computed_recommendation", "historical": true}, "DonchCh20.Lower": {"label": "Donchian Channels Lower Band (20)", "format": "round", "historical": false}, "DonchCh20.Upper": {"label": "Donchian Channels Upper Band (20)", "format": "round", "historical": false}, "EMA5": {"label": "Exponential Moving Average (5)", "format": "computed_recommendation", "historical": false}, "EMA10": {"label": "Exponential Moving Average (10)", "format": "computed_recommendation", "historical": false}, "EMA20": {"label": "Exponential Moving Average (20)", "format": "computed_recommendation", "historical": false}, "EMA30": {"label": "Exponential Moving Average (30)", "format": "computed_recommendation", "historical": false}, "EMA50": {"label": "Exponential Moving Average (50)", "format": "computed_recommendation", "historical": false}, "EMA100": {"label": "Exponential Moving Average (100)", "format": "computed_recommendation", "historical": false}, "EMA200": {"label": "Exponential Moving Average (200)", "format": "computed_recommendation", "historical": false}, "market_cap_diluted_calc": {"label": "Fully Diluted Market Cap", "format": "missing", "historical": false}, "gap": {"label": "Gap %", "format": "percent", "historical": false}, "HullMA9": {"label": "Hull Moving Average (9)", "format": "recommendation", "historical": false}, "Ichimoku.BLine": {"label": "Ichimoku Base Line (9, 26, 52, 26)", "format": "computed_recommendation", "historical": false}, "Ichimoku.CLine": {"label": "Ichimoku Conversion Line (9, 26, 52, 26)", "format": "round", "historical": false}, "Ichimoku.Lead1": {"label": "Ichimoku Leading Span A (9, 26, 52, 26)", "format": "float", "historical": false}, "Ichimoku.Lead2": {"label": "Ichimoku Leading Span B (9, 26, 52, 26)", "format": "round", "historical": false}, "KltChnl.lower": {"label": "Keltner Channels Lower Band (20)", "format": "float", "historical": false}, "KltChnl.upper": {"label": "Keltner Channels Upper Band (20)", "format": "float", "historical": false}, "MACD.macd": {"label": "MACD Level (12, 26)", "format": "computed_recommendation", "historical": false}, "MACD.signal": {"label": "MACD Signal (12, 26)", "format": "float", "historical": false}, "market_cap_calc": {"label": "Market Capitalization", "format": "missing", "historical": false}, "Mom": {"label": "Momentum (10)", "format": "computed_recommendation", "historical": true}, "Perf.1M": {"label": "Monthly Performance", "format": "percent", "historical": false}, "Recommend.MA": {"label": "Moving Averages Rating", "format": "rating", "historical": false}, "ADX-DI": {"label": "Negative Directional Indicator (14)", "format": "round", "historical": true}, "open": {"label": "Open", "format": "float", "historical": false}, "Recommend.Other": {"label": "Oscillators Rating", "format": "rating", "historical": false}, "P.SAR": {"label": "Parabolic SAR", "format": "computed_recommendation", "historical": false}, "candlestick": {"label": "Pattern", "format": "missing", "historical": false}, "Pivot.M.Camarilla.Middle": {"label": "Pivot Camarilla P", "format": "float", "historical": false}, "Pivot.M.Camarilla.R1": {"label": "Pivot Camarilla R1", "format": "float", "historical": false}, "Pivot.M.Camarilla.R2": {"label": "Pivot Camarilla R2", "format": "float", "historical": false}, "Pivot.M.Camarilla.R3": {"label": "Pivot Camarilla R3", "format": "round", "historical": false}, "Pivot.M.Camarilla.S1": {"label": "Pivot Camarilla S1", "format": "float", "historical": false}, "Pivot.M.Camarilla.S2": {"label": "Pivot Camarilla S2", "format": "float", "historical": false}, "Pivot.M.Camarilla.S3": {"label": "Pivot Camarilla S3", "format": "round", "historical": false}, "Pivot.M.Classic.Middle": {"label": "Pivot Classic P", "format": "float", "historical": false}, "Pivot.M.Classic.R1": {"label": "Pivot Classic R1", "format": "float", "historical": false}, "Pivot.M.Classic.R2": {"label": "Pivot Classic R2", "format": "float", "historical": false}, "Pivot.M.Classic.R3": {"label": "Pivot Classic R3", "format": "float", "historical": false}, "Pivot.M.Classic.S1": {"label": "Pivot Classic S1", "format": "float", "historical": false}, "Pivot.M.Classic.S2": {"label": "Pivot Classic S2", "format": "float", "historical": false}, "Pivot.M.Classic.S3": {"label": "Pivot Classic S3", "format": "float", "historical": false}, "Pivot.M.Demark.Middle": {"label": "Pivot DM P", "format": "round", "historical": false}, "Pivot.M.Demark.R1": {"label": "Pivot DM R1", "format": "round", "historical": false}, "Pivot.M.Demark.S1": {"label": "Pivot DM S1", "format": "round", "historical": false}, "Pivot.M.Fibonacci.Middle": {"label": "Pivot Fibonacci P", "format": "float", "historical": false}, "Pivot.M.Fibonacci.R1": {"label": "Pivot Fibonacci R1", "format": "float", "historical": false}, "Pivot.M.Fibonacci.R2": {"label": "Pivot Fibonacci R2", "format": "float", "historical": false}, "Pivot.M.Fibonacci.R3": {"label": "Pivot Fibonacci R3", "format": "float", "historical": false}, "Pivot.M.Fibonacci.S1": {"label": "Pivot Fibonacci S1", "format": "float", "historical": false}, "Pivot.M.Fibonacci.S2": {"label": "Pivot Fibonacci S2", "format": "float", "historical": false}, "Pivot.M.Fibonacci.S3": {"label": "Pivot Fibonacci S3", "format": "float", "historical": false}, "Pivot.M.Woodie.Middle": {"label": "Pivot Woodie P", "format": "round", "historical": false}, "Pivot.M.Woodie.R1": {"label": "Pivot Woodie R1", "format": "round", "historical": false}, "Pivot.M.Woodie.R2": {"label": "Pivot Woodie R2", "format": "round", "historical": false}, "Pivot.M.Woodie.R3": {"label": "Pivot Woodie R3", "format": "round", "historical": false}, "Pivot.M.Woodie.S1": {"label": "Pivot Woodie S1", "format": "round", "historical": false}, "Pivot.M.Woodie.S2": {"label": "Pivot Woodie S2", "format": "round", "historical": false}, "Pivot.M.Woodie.S3": {"label": "Pivot Woodie S3", "format": "round", "historical": false}, "ADX+DI": {"label": "Positive Directional Indicator (14)", "format": "round", "historical": true}, "ROC": {"label": "Rate Of Change (9)", "format": "round", "historical": false}, "RSI7": {"label": "Relative Strength Index (7)", "format": "computed_recommendation", "historical": true}, "RSI": {"label": "Relative Strength Index (14)", "format": "computed_recommendation", "historical": true}, "relative_volume_10d_calc": {"label": "Relative Volume", "format": "round", "historical": false}, "relative_volume_intraday.5": {"label": "Relative Volume at Time", "format": "round", "historical": false}, "SMA5": {"label": "Simple Moving Average (5)", "format": "computed_recommendation", "historical": false}, "SMA10": {"label": "Simple Moving Average (10)", "format": "computed_recommendation", "historical": false}, "SMA20": {"label": "Simple Moving Average (20)", "format": "computed_recommendation", "historical": false}, "SMA30": {"label": "Simple Moving Average (30)", "format": "computed_recommendation", "historical": false}, "SMA50": {"label": "Simple Moving Average (50)", "format": "computed_recommendation", "historical": false}, "SMA100": {"label": "Simple Moving Average (100)", "format": "computed_recommendation", "historical": false}, "SMA200": {"label": "Simple Moving Average (200)", "format": "computed_recommendation", "historical": false}, "Stoch.D": {"label": "Stochastic %D (14, 3, 3)", "format": "round", "historical": true}, "Stoch.K": {"label": "Stochastic %K (14, 3, 3)", "format": "computed_recommendation", "historical": true}, "Stoch.RSI.K": {"label": "Stochastic RSI Fast (3, 3, 14, 14)", "format": "computed_recommendation", "historical": false}, "Stoch.RSI.D": {"label": "Stochastic RSI Slow (3, 3, 14, 14)", "format": "round", "historical": false}, "total_shares_diluted": {"label": "Total Coins", "format": "missing", "historical": false}, "total_value_traded": {"label": "Traded Volume", "format": "missing", "historical": false}, "UO": {"label": "Ultimate Oscillator (7, 14, 28)", "format": "recommendation", "historical": false}, "Volatility.D": {"label": "Volatility", "format": "percent", "historical": false}, "Volatility.M": {"label": "Volatility Month", "format": "percent", "historical": false}, "Volatility.W": {"label": "Volatility Week", "format": "percent", "historical": false}, "VWAP": {"label": "Volume Weighted Average Price", "format": "float", "historical": false}, "VWMA": {"label": "Volume Weighted Moving Average (20)", "format": "recommendation", "historical": false}, "Perf.W": {"label": "Weekly Performance", "format": "percent", "historical": false}, "W.R": {"label": "Williams Percent Range (14)", "format": "computed_recommendation", "historical": false}, "Perf.Y": {"label": "Yearly Performance", "format": "percent", "historical": false}, "Perf.YTD": {"label": "YTD Performance", "format": "percent", "historical": false}} \ No newline at end of file diff --git a/generate/data/country.json b/generate/data/country.json new file mode 100644 index 0000000..449c621 --- /dev/null +++ b/generate/data/country.json @@ -0,0 +1,83 @@ +{ + "Country": [ + "Any", + "Albania", + "Argentina", + "Australia", + "Austria", + "Azerbaijan", + "Bahamas", + "Barbados", + "Belgium", + "Bermuda", + "Brazil", + "British Virgin Islands", + "Cambodia", + "Canada", + "Cayman Islands", + "Chile", + "China", + "Colombia", + "Costa Rica", + "Cyprus", + "Czech Republic", + "Denmark", + "Dominican Republic", + "Egypt", + "Faroe Islands", + "Finland", + "France", + "Germany", + "Gibraltar", + "Greece", + "Hong Kong", + "Hungary", + "Iceland", + "India", + "Indonesia", + "Ireland", + "Israel", + "Italy", + "Jamaica", + "Japan", + "Jordan", + "Kazakhstan", + "Luxembourg", + "Macau", + "Macedonia", + "Malaysia", + "Malta", + "Mauritius", + "Mexico", + "Monaco", + "Mongolia", + "Montenegro", + "Netherlands", + "New Zealand", + "Norway", + "Panama", + "Peru", + "Philippines", + "Poland", + "Portugal", + "Puerto Rico", + "Romania", + "Russian Federation", + "Singapore", + "South Africa", + "South Korea", + "Spain", + "Sweden", + "Switzerland", + "Taiwan", + "Tanzania", + "Thailand", + "Turkey", + "U.S. Virgin Islands", + "United Arab Emirates", + "United Kingdom", + "United States", + "Uruguay", + "Vietnam" + ] +} \ No newline at end of file diff --git a/generate/data/crypto.json b/generate/data/crypto.json new file mode 100644 index 0000000..d9fdf2d --- /dev/null +++ b/generate/data/crypto.json @@ -0,0 +1,732 @@ +{ + "change": { + "label": "Change %", + "format": "percent", + "historical": false + }, + "change_abs": { + "label": "Change", + "format": "float", + "historical": false + }, + "exchange": { + "label": "Exchange", + "format": "text", + "historical": false + }, + "high": { + "label": "High", + "format": "float", + "historical": false + }, + "low": { + "label": "Low", + "format": "float", + "historical": false + }, + "close": { + "label": "Price", + "format": "float", + "historical": false + }, + "Recommend.All": { + "label": "Technical Rating", + "format": "rating", + "historical": false + }, + "volume": { + "label": "Volume", + "format": "number_group", + "historical": false + }, + "24h_vol_change|5": { + "label": "Volume 24h Change %", + "format": "percent", + "historical": false + }, + "24h_vol|5": { + "label": "Volume 24h in USD", + "format": "number_group", + "historical": false + }, + "High.1M": { + "label": "1-Month High", + "format": "round", + "historical": false + }, + "Low.1M": { + "label": "1-Month Low", + "format": "round", + "historical": false + }, + "High.3M": { + "label": "3-Month High", + "format": "round", + "historical": false + }, + "Low.3M": { + "label": "3-Month Low", + "format": "round", + "historical": false + }, + "Perf.3M": { + "label": "3-Month Performance", + "format": "percent", + "historical": false + }, + "Perf.5Y": { + "label": "5Y Performance", + "format": "percent", + "historical": false + }, + "High.6M": { + "label": "6-Month High", + "format": "round", + "historical": false + }, + "Low.6M": { + "label": "6-Month Low", + "format": "round", + "historical": false + }, + "Perf.6M": { + "label": "6-Month Performance", + "format": "percent", + "historical": false + }, + "price_52_week_high": { + "label": "52 Week High", + "format": "round", + "historical": false + }, + "price_52_week_low": { + "label": "52 Week Low", + "format": "round", + "historical": false + }, + "High.All": { + "label": "All Time High", + "format": "round", + "historical": false + }, + "Low.All": { + "label": "All Time Low", + "format": "round", + "historical": false + }, + "Perf.All": { + "label": "All Time Performance", + "format": "percent", + "historical": false + }, + "Aroon.Down": { + "label": "Aroon Down (14)", + "format": "round", + "historical": false + }, + "Aroon.Up": { + "label": "Aroon Up (14)", + "format": "round", + "historical": false + }, + "ask": { + "label": "Ask", + "format": "float", + "historical": false + }, + "total_shares_outstanding": { + "label": "Available Coins", + "format": "missing", + "historical": false + }, + "ADR": { + "label": "Average Day Range (14)", + "format": "float", + "historical": false + }, + "ADX": { + "label": "Average Directional Index (14)", + "format": "computed_recommendation", + "historical": false + }, + "ATR": { + "label": "Average True Range (14)", + "format": "float", + "historical": false + }, + "average_volume_10d_calc": { + "label": "Average Volume (10 day)", + "format": "number_group", + "historical": false + }, + "average_volume_30d_calc": { + "label": "Average Volume (30 day)", + "format": "number_group", + "historical": false + }, + "average_volume_60d_calc": { + "label": "Average Volume (60 day)", + "format": "number_group", + "historical": false + }, + "average_volume_90d_calc": { + "label": "Average Volume (90 day)", + "format": "number_group", + "historical": false + }, + "AO": { + "label": "Awesome Oscillator", + "format": "computed_recommendation", + "historical": true + }, + "bid": { + "label": "Bid", + "format": "float", + "historical": false + }, + "BB.lower": { + "label": "Bollinger Lower Band (20)", + "format": "computed_recommendation", + "historical": false + }, + "BB.upper": { + "label": "Bollinger Upper Band (20)", + "format": "computed_recommendation", + "historical": false + }, + "BBPower": { + "label": "Bull Bear Power", + "format": "recommendation", + "historical": false + }, + "change.60": { + "label": "Change 1h, %", + "format": "percent", + "historical": false + }, + "change_abs.60": { + "label": "Change 1h", + "format": "round", + "historical": false + }, + "change.1": { + "label": "Change 1m, %", + "format": "percent", + "historical": false + }, + "change_abs.1": { + "label": "Change 1m", + "format": "round", + "historical": false + }, + "change.1M": { + "label": "Change 1M, %", + "format": "percent", + "historical": false + }, + "change_abs.1M": { + "label": "Change 1M", + "format": "round", + "historical": false + }, + "change.1W": { + "label": "Change 1W, %", + "format": "percent", + "historical": false + }, + "change_abs.1W": { + "label": "Change 1W", + "format": "round", + "historical": false + }, + "change.240": { + "label": "Change 4h, %", + "format": "percent", + "historical": false + }, + "change_abs.240": { + "label": "Change 4h", + "format": "round", + "historical": false + }, + "change.5": { + "label": "Change 5m, %", + "format": "percent", + "historical": false + }, + "change_abs.5": { + "label": "Change 5m", + "format": "round", + "historical": false + }, + "change.15": { + "label": "Change 15m, %", + "format": "percent", + "historical": false + }, + "change_abs.15": { + "label": "Change 15m", + "format": "round", + "historical": false + }, + "change_from_open": { + "label": "Change from Open %", + "format": "percent", + "historical": false + }, + "change_from_open_abs": { + "label": "Change from Open", + "format": "float", + "historical": false + }, + "CCI20": { + "label": "Commodity Channel Index (20)", + "format": "computed_recommendation", + "historical": true + }, + "DonchCh20.Lower": { + "label": "Donchian Channels Lower Band (20)", + "format": "round", + "historical": false + }, + "DonchCh20.Upper": { + "label": "Donchian Channels Upper Band (20)", + "format": "round", + "historical": false + }, + "EMA5": { + "label": "Exponential Moving Average (5)", + "format": "computed_recommendation", + "historical": false + }, + "EMA10": { + "label": "Exponential Moving Average (10)", + "format": "computed_recommendation", + "historical": false + }, + "EMA20": { + "label": "Exponential Moving Average (20)", + "format": "computed_recommendation", + "historical": false + }, + "EMA30": { + "label": "Exponential Moving Average (30)", + "format": "computed_recommendation", + "historical": false + }, + "EMA50": { + "label": "Exponential Moving Average (50)", + "format": "computed_recommendation", + "historical": false + }, + "EMA100": { + "label": "Exponential Moving Average (100)", + "format": "computed_recommendation", + "historical": false + }, + "EMA200": { + "label": "Exponential Moving Average (200)", + "format": "computed_recommendation", + "historical": false + }, + "market_cap_diluted_calc": { + "label": "Fully Diluted Market Cap", + "format": "missing", + "historical": false + }, + "gap": { + "label": "Gap %", + "format": "percent", + "historical": false + }, + "HullMA9": { + "label": "Hull Moving Average (9)", + "format": "recommendation", + "historical": false + }, + "Ichimoku.BLine": { + "label": "Ichimoku Base Line (9, 26, 52, 26)", + "format": "computed_recommendation", + "historical": false + }, + "Ichimoku.CLine": { + "label": "Ichimoku Conversion Line (9, 26, 52, 26)", + "format": "round", + "historical": false + }, + "Ichimoku.Lead1": { + "label": "Ichimoku Leading Span A (9, 26, 52, 26)", + "format": "float", + "historical": false + }, + "Ichimoku.Lead2": { + "label": "Ichimoku Leading Span B (9, 26, 52, 26)", + "format": "round", + "historical": false + }, + "KltChnl.lower": { + "label": "Keltner Channels Lower Band (20)", + "format": "float", + "historical": false + }, + "KltChnl.upper": { + "label": "Keltner Channels Upper Band (20)", + "format": "float", + "historical": false + }, + "MACD.macd": { + "label": "MACD Level (12, 26)", + "format": "computed_recommendation", + "historical": false + }, + "MACD.signal": { + "label": "MACD Signal (12, 26)", + "format": "float", + "historical": false + }, + "market_cap_calc": { + "label": "Market Capitalization", + "format": "missing", + "historical": false + }, + "Mom": { + "label": "Momentum (10)", + "format": "computed_recommendation", + "historical": true + }, + "Perf.1M": { + "label": "Monthly Performance", + "format": "percent", + "historical": false + }, + "Recommend.MA": { + "label": "Moving Averages Rating", + "format": "rating", + "historical": false + }, + "ADX-DI": { + "label": "Negative Directional Indicator (14)", + "format": "round", + "historical": true + }, + "open": { + "label": "Open", + "format": "float", + "historical": false + }, + "Recommend.Other": { + "label": "Oscillators Rating", + "format": "rating", + "historical": false + }, + "P.SAR": { + "label": "Parabolic SAR", + "format": "computed_recommendation", + "historical": false + }, + "candlestick": { + "label": "Pattern", + "format": "missing", + "historical": false + }, + "Pivot.M.Camarilla.Middle": { + "label": "Pivot Camarilla P", + "format": "float", + "historical": false + }, + "Pivot.M.Camarilla.R1": { + "label": "Pivot Camarilla R1", + "format": "float", + "historical": false + }, + "Pivot.M.Camarilla.R2": { + "label": "Pivot Camarilla R2", + "format": "float", + "historical": false + }, + "Pivot.M.Camarilla.R3": { + "label": "Pivot Camarilla R3", + "format": "round", + "historical": false + }, + "Pivot.M.Camarilla.S1": { + "label": "Pivot Camarilla S1", + "format": "float", + "historical": false + }, + "Pivot.M.Camarilla.S2": { + "label": "Pivot Camarilla S2", + "format": "float", + "historical": false + }, + "Pivot.M.Camarilla.S3": { + "label": "Pivot Camarilla S3", + "format": "round", + "historical": false + }, + "Pivot.M.Classic.Middle": { + "label": "Pivot Classic P", + "format": "float", + "historical": false + }, + "Pivot.M.Classic.R1": { + "label": "Pivot Classic R1", + "format": "float", + "historical": false + }, + "Pivot.M.Classic.R2": { + "label": "Pivot Classic R2", + "format": "float", + "historical": false + }, + "Pivot.M.Classic.R3": { + "label": "Pivot Classic R3", + "format": "float", + "historical": false + }, + "Pivot.M.Classic.S1": { + "label": "Pivot Classic S1", + "format": "float", + "historical": false + }, + "Pivot.M.Classic.S2": { + "label": "Pivot Classic S2", + "format": "float", + "historical": false + }, + "Pivot.M.Classic.S3": { + "label": "Pivot Classic S3", + "format": "float", + "historical": false + }, + "Pivot.M.Demark.Middle": { + "label": "Pivot DM P", + "format": "round", + "historical": false + }, + "Pivot.M.Demark.R1": { + "label": "Pivot DM R1", + "format": "round", + "historical": false + }, + "Pivot.M.Demark.S1": { + "label": "Pivot DM S1", + "format": "round", + "historical": false + }, + "Pivot.M.Fibonacci.Middle": { + "label": "Pivot Fibonacci P", + "format": "float", + "historical": false + }, + "Pivot.M.Fibonacci.R1": { + "label": "Pivot Fibonacci R1", + "format": "float", + "historical": false + }, + "Pivot.M.Fibonacci.R2": { + "label": "Pivot Fibonacci R2", + "format": "float", + "historical": false + }, + "Pivot.M.Fibonacci.R3": { + "label": "Pivot Fibonacci R3", + "format": "float", + "historical": false + }, + "Pivot.M.Fibonacci.S1": { + "label": "Pivot Fibonacci S1", + "format": "float", + "historical": false + }, + "Pivot.M.Fibonacci.S2": { + "label": "Pivot Fibonacci S2", + "format": "float", + "historical": false + }, + "Pivot.M.Fibonacci.S3": { + "label": "Pivot Fibonacci S3", + "format": "float", + "historical": false + }, + "Pivot.M.Woodie.Middle": { + "label": "Pivot Woodie P", + "format": "round", + "historical": false + }, + "Pivot.M.Woodie.R1": { + "label": "Pivot Woodie R1", + "format": "round", + "historical": false + }, + "Pivot.M.Woodie.R2": { + "label": "Pivot Woodie R2", + "format": "round", + "historical": false + }, + "Pivot.M.Woodie.R3": { + "label": "Pivot Woodie R3", + "format": "round", + "historical": false + }, + "Pivot.M.Woodie.S1": { + "label": "Pivot Woodie S1", + "format": "round", + "historical": false + }, + "Pivot.M.Woodie.S2": { + "label": "Pivot Woodie S2", + "format": "round", + "historical": false + }, + "Pivot.M.Woodie.S3": { + "label": "Pivot Woodie S3", + "format": "round", + "historical": false + }, + "ADX+DI": { + "label": "Positive Directional Indicator (14)", + "format": "round", + "historical": true + }, + "ROC": { + "label": "Rate Of Change (9)", + "format": "round", + "historical": false + }, + "RSI7": { + "label": "Relative Strength Index (7)", + "format": "computed_recommendation", + "historical": true + }, + "RSI": { + "label": "Relative Strength Index (14)", + "format": "computed_recommendation", + "historical": true + }, + "relative_volume_10d_calc": { + "label": "Relative Volume", + "format": "round", + "historical": false + }, + "relative_volume_intraday.5": { + "label": "Relative Volume at Time", + "format": "round", + "historical": false + }, + "SMA5": { + "label": "Simple Moving Average (5)", + "format": "computed_recommendation", + "historical": false + }, + "SMA10": { + "label": "Simple Moving Average (10)", + "format": "computed_recommendation", + "historical": false + }, + "SMA20": { + "label": "Simple Moving Average (20)", + "format": "computed_recommendation", + "historical": false + }, + "SMA30": { + "label": "Simple Moving Average (30)", + "format": "computed_recommendation", + "historical": false + }, + "SMA50": { + "label": "Simple Moving Average (50)", + "format": "computed_recommendation", + "historical": false + }, + "SMA100": { + "label": "Simple Moving Average (100)", + "format": "computed_recommendation", + "historical": false + }, + "SMA200": { + "label": "Simple Moving Average (200)", + "format": "computed_recommendation", + "historical": false + }, + "Stoch.D": { + "label": "Stochastic %D (14, 3, 3)", + "format": "round", + "historical": true + }, + "Stoch.K": { + "label": "Stochastic %K (14, 3, 3)", + "format": "computed_recommendation", + "historical": true + }, + "Stoch.RSI.K": { + "label": "Stochastic RSI Fast (3, 3, 14, 14)", + "format": "computed_recommendation", + "historical": false + }, + "Stoch.RSI.D": { + "label": "Stochastic RSI Slow (3, 3, 14, 14)", + "format": "round", + "historical": false + }, + "total_shares_diluted": { + "label": "Total Coins", + "format": "missing", + "historical": false + }, + "total_value_traded": { + "label": "Traded Volume", + "format": "missing", + "historical": false + }, + "UO": { + "label": "Ultimate Oscillator (7, 14, 28)", + "format": "recommendation", + "historical": false + }, + "Volatility.D": { + "label": "Volatility", + "format": "percent", + "historical": false + }, + "Volatility.M": { + "label": "Volatility Month", + "format": "percent", + "historical": false + }, + "Volatility.W": { + "label": "Volatility Week", + "format": "percent", + "historical": false + }, + "VWAP": { + "label": "Volume Weighted Average Price", + "format": "float", + "historical": false + }, + "VWMA": { + "label": "Volume Weighted Moving Average (20)", + "format": "recommendation", + "historical": false + }, + "Perf.W": { + "label": "Weekly Performance", + "format": "percent", + "historical": false + }, + "W.R": { + "label": "Williams Percent Range (14)", + "format": "computed_recommendation", + "historical": false + }, + "Perf.Y": { + "label": "Yearly Performance", + "format": "percent", + "historical": false + }, + "Perf.YTD": { + "label": "YTD Performance", + "format": "percent", + "historical": false + } +} \ No newline at end of file diff --git a/generate/data/exchange.json b/generate/data/exchange.json new file mode 100644 index 0000000..0758733 --- /dev/null +++ b/generate/data/exchange.json @@ -0,0 +1,9 @@ +{ + "Exchange": [ + "Any", + "NYSE ARCA", + "NASDAQ", + "NYSE", + "OTC" + ] +} \ No newline at end of file diff --git a/generate/forex.json b/generate/data/forex.json similarity index 100% rename from generate/forex.json rename to generate/data/forex.json diff --git a/generate/data/index.json b/generate/data/index.json new file mode 100644 index 0000000..ccf2045 --- /dev/null +++ b/generate/data/index.json @@ -0,0 +1,48 @@ +{ + "Index": [ + "Any", + "Dow Jones Composite Average", + "Dow Jones Industrial Average", + "Dow Jones Transportation Average", + "Dow Jones Utility Average", + "KBW NASDAQ BANK INDEX", + "MINI RUSSELL 2000 INDEX", + "NASDAQ 100", + "NASDAQ 100 TECHNOLOGY SECTOR", + "NASDAQ BANK", + "NASDAQ BIOTECHNOLOGY", + "NASDAQ COMPOSITE", + "NASDAQ COMPUTER", + "NASDAQ GOLDEN DRAGON CHINA INDEX", + "NASDAQ INDUSTRIAL", + "NASDAQ INSURANCE", + "NASDAQ OTHER FINANCE", + "NASDAQ TELECOMMUNICATIONS", + "NASDAQ TRANSPORTATION", + "NASDAQ US BENCHMARK FOOD PRODUCERS INDEX", + "NYSE ARCA MAJOR MARKET", + "PHLX GOLD AND SILVER SECTOR INDEX", + "PHLX HOUSING SECTOR", + "PHLX OIL SERVICE SECTOR", + "PHLX SEMICONDUCTOR", + "PHLX UTILITY SECTOR", + "RUSSELL 1000", + "RUSSELL 2000", + "RUSSELL 3000", + "S&P 100", + "S&P 400", + "S&P 500", + "S&P 500 Communication Services", + "S&P 500 Consumer Discretionary", + "S&P 500 Consumer Staples", + "S&P 500 ESG INDEX", + "S&P 500 Energy", + "S&P 500 Financials", + "S&P 500 Health Care", + "S&P 500 Industrials", + "S&P 500 Information Technology", + "S&P 500 Materials", + "S&P 500 Real Estate", + "S&P 500 Utilities" + ] +} \ No newline at end of file diff --git a/generate/data/industry.json b/generate/data/industry.json new file mode 100644 index 0000000..2779e27 --- /dev/null +++ b/generate/data/industry.json @@ -0,0 +1,135 @@ +{ + "Industry": [ + "Any", + "Advertising/Marketing Services", + "Aerospace & Defense", + "Agricultural Commodities/Milling", + "Air Freight/Couriers", + "Airlines", + "Alternative Power Generation", + "Aluminum", + "Apparel/Footwear", + "Apparel/Footwear Retail", + "Auto Parts: OEM", + "Automotive Aftermarket", + "Beverages: Alcoholic", + "Beverages: Non-Alcoholic", + "Biotechnology", + "Broadcasting", + "Building Products", + "Cable/Satellite TV", + "Casinos/Gaming", + "Catalog/Specialty Distribution", + "Chemicals: Agricultural", + "Chemicals: Major Diversified", + "Chemicals: Specialty", + "Coal", + "Commercial Printing/Forms", + "Computer Communications", + "Computer Peripherals", + "Computer Processing Hardware", + "Construction Materials", + "Consumer Sundries", + "Containers/Packaging", + "Contract Drilling", + "Data Processing Services", + "Department Stores", + "Discount Stores", + "Drugstore Chains", + "Electric Utilities", + "Electrical Products", + "Electronic Components", + "Electronic Equipment/Instruments", + "Electronic Production Equipment", + "Electronics Distributors", + "Electronics/Appliance Stores", + "Electronics/Appliances", + "Engineering & Construction", + "Environmental Services", + "Finance/Rental/Leasing", + "Financial Conglomerates", + "Financial Publishing/Services", + "Food Distributors", + "Food Retail", + "Food: Major Diversified", + "Food: Meat/Fish/Dairy", + "Food: Specialty/Candy", + "Forest Products", + "Gas Distributors", + "General Government", + "Home Furnishings", + "Home Improvement Chains", + "Homebuilding", + "Hospital/Nursing Management", + "Hotels/Resorts/Cruise lines", + "Household/Personal Care", + "Industrial Conglomerates", + "Industrial Machinery", + "Industrial Specialties", + "Information Technology Services", + "Insurance Brokers/Services", + "Integrated Oil", + "Internet Retail", + "Internet Software/Services", + "Investment Banks/Brokers", + "Investment Managers", + "Investment Trusts/Mutual Funds", + "Life/Health Insurance", + "Major Banks", + "Major Telecommunications", + "Managed Health Care", + "Marine Shipping", + "Media Conglomerates", + "Medical Distributors", + "Medical Specialties", + "Medical/Nursing Services", + "Metal Fabrication", + "Miscellaneous", + "Miscellaneous Commercial Services", + "Miscellaneous Manufacturing", + "Motor Vehicles", + "Movies/Entertainment", + "Multi-Line Insurance", + "Office Equipment/Supplies", + "Oil & Gas Pipelines", + "Oil & Gas Production", + "Oil Refining/Marketing", + "Oilfield Services/Equipment", + "Other Consumer Services", + "Other Consumer Specialties", + "Other Metals/Minerals", + "Other Transportation", + "Packaged Software", + "Personnel Services", + "Pharmaceuticals: Generic", + "Pharmaceuticals: Major", + "Pharmaceuticals: Other", + "Precious Metals", + "Property/Casualty Insurance", + "Publishing: Books/Magazines", + "Publishing: Newspapers", + "Pulp & Paper", + "Railroads", + "Real Estate Development", + "Real Estate Investment Trusts", + "Recreational Products", + "Regional Banks", + "Restaurants", + "Savings Banks", + "Semiconductors", + "Services to the Health Industry", + "Specialty Insurance", + "Specialty Stores", + "Specialty Telecommunications", + "Steel", + "Telecommunications Equipment", + "Textiles", + "Tobacco", + "Tools & Hardware", + "Trucking", + "Trucks/Construction/Farm Machinery", + "Water Utilities", + "Wholesale Distributors", + "Wireless Telecommunications" + ] +} \ No newline at end of file diff --git a/generate/data/main.json b/generate/data/main.json new file mode 100644 index 0000000..46fa7bd --- /dev/null +++ b/generate/data/main.json @@ -0,0 +1,11 @@ +{ + "main": [ + "logoid", + "name", + "description", + "type", + "subtype", + "currency", + "fundamental_currency_code" + ] +} \ No newline at end of file diff --git a/generate/data/patterns.json b/generate/data/patterns.json new file mode 100644 index 0000000..b3dfabf --- /dev/null +++ b/generate/data/patterns.json @@ -0,0 +1,31 @@ +{ + "patterns": [ + "Candle.AbandonedBaby.Bearish", + "Candle.AbandonedBaby.Bullish", + "Candle.Engulfing.Bearish", + "Candle.Harami.Bearish", + "Candle.Engulfing.Bullish", + "Candle.Harami.Bullish", + "Candle.Doji", + "Candle.Doji.Dragonfly", + "Candle.EveningStar", + "Candle.Doji.Gravestone", + "Candle.Hammer", + "Candle.HangingMan", + "Candle.InvertedHammer", + "Candle.Kicking.Bearish", + "Candle.Kicking.Bullish", + "Candle.LongShadow.Lower", + "Candle.LongShadow.Upper", + "Candle.Marubozu.Black", + "Candle.Marubozu.White", + "Candle.MorningStar", + "Candle.ShootingStar", + "Candle.SpinningTop.Black", + "Candle.SpinningTop.White", + "Candle.3BlackCrows", + "Candle.3WhiteSoldiers", + "Candle.TriStar.Bearish", + "Candle.TriStar.Bullish" + ] +} \ No newline at end of file diff --git a/generate/data/sector.json b/generate/data/sector.json new file mode 100644 index 0000000..e31e40b --- /dev/null +++ b/generate/data/sector.json @@ -0,0 +1,26 @@ +{ + "Sector": [ + "Any", + "Commercial Services", + "Communications", + "Consumer Durables", + "Consumer Non-Durables", + "Consumer Services", + "Distribution Services", + "Electronic Technology", + "Energy Minerals", + "Finance", + "Government", + "Health Services", + "Health Technology", + "Industrial Services", + "Miscellaneous", + "Non-Energy Minerals", + "Process Industries", + "Producer Manufacturing", + "Retail Trade", + "Technology Services", + "Transportation", + "Utilities" + ] +} \ No newline at end of file diff --git a/generate/stock.json b/generate/data/stock.json similarity index 100% rename from generate/stock.json rename to generate/data/stock.json diff --git a/generate/data/submarket.json b/generate/data/submarket.json new file mode 100644 index 0000000..672ce2f --- /dev/null +++ b/generate/data/submarket.json @@ -0,0 +1,8 @@ +{ + "Submarket": [ + "Any", + "OTCQB", + "OTCQX", + "PINK" + ] +} \ No newline at end of file diff --git a/generate/data/symbol type.json b/generate/data/symbol type.json new file mode 100644 index 0000000..a87a66a --- /dev/null +++ b/generate/data/symbol type.json @@ -0,0 +1,16 @@ +{ + "Symbol Type": [ + "Any", + "Closed-end fund", + "Common Stock", + "Depositary Receipt", + "ETF", + "ETN", + "Mutual fund", + "Preferred Stock", + "REIT", + "Structured", + "Trust fund", + "UIT" + ] +} \ No newline at end of file diff --git a/generate/data/time_intervals.json b/generate/data/time_intervals.json new file mode 100644 index 0000000..dde59b2 --- /dev/null +++ b/generate/data/time_intervals.json @@ -0,0 +1,129 @@ +{ + "columns": [ + "ADR", + "ADX", + "ADX+DI", + "ADX-DI", + "AO", + "ATR", + "Aroon.Down", + "Aroon.Up", + "BB.lower", + "BB.upper", + "BBPower", + "CCI20", + "DonchCh20.Lower", + "DonchCh20.Upper", + "EMA10", + "EMA100", + "EMA20", + "EMA200", + "EMA30", + "EMA5", + "EMA50", + "HullMA9", + "Ichimoku.BLine", + "Ichimoku.CLine", + "Ichimoku.Lead1", + "Ichimoku.Lead2", + "KltChnl.lower", + "KltChnl.upper", + "MACD.macd", + "MACD.signal", + "Mom", + "P.SAR", + "Pivot.M.Camarilla.Middle", + "Pivot.M.Camarilla.R1", + "Pivot.M.Camarilla.R2", + "Pivot.M.Camarilla.R3", + "Pivot.M.Camarilla.S1", + "Pivot.M.Camarilla.S2", + "Pivot.M.Camarilla.S3", + "Pivot.M.Classic.Middle", + "Pivot.M.Classic.R1", + "Pivot.M.Classic.R2", + "Pivot.M.Classic.R3", + "Pivot.M.Classic.S1", + "Pivot.M.Classic.S2", + "Pivot.M.Classic.S3", + "Pivot.M.Demark.Middle", + "Pivot.M.Demark.R1", + "Pivot.M.Demark.S1", + "Pivot.M.Fibonacci.Middle", + "Pivot.M.Fibonacci.R1", + "Pivot.M.Fibonacci.R2", + "Pivot.M.Fibonacci.R3", + "Pivot.M.Fibonacci.S1", + "Pivot.M.Fibonacci.S2", + "Pivot.M.Fibonacci.S3", + "Pivot.M.Woodie.Middle", + "Pivot.M.Woodie.R1", + "Pivot.M.Woodie.R2", + "Pivot.M.Woodie.R3", + "Pivot.M.Woodie.S1", + "Pivot.M.Woodie.S2", + "Pivot.M.Woodie.S3", + "ROC", + "RSI", + "RSI7", + "Recommend.All", + "Recommend.MA", + "Recommend.Other", + "SMA10", + "SMA100", + "SMA20", + "SMA200", + "SMA30", + "SMA5", + "SMA50", + "Stoch.D", + "Stoch.K", + "Stoch.RSI.D", + "Stoch.RSI.K", + "UO", + "VWAP", + "VWMA", + "W.R", + "change", + "close", + "gap", + "high", + "low", + "open", + "MoneyFlow", + "Value.Traded", + "relative_volume_10d_calc", + "candlestick", + "Candle.AbandonedBaby.Bearish", + "Candle.AbandonedBaby.Bullish", + "Candle.Engulfing.Bearish", + "Candle.Harami.Bearish", + "Candle.Engulfing.Bullish", + "Candle.Harami.Bullish", + "Candle.Doji", + "Candle.Doji.Dragonfly", + "Candle.EveningStar", + "Candle.Doji.Gravestone", + "Candle.Hammer", + "Candle.HangingMan", + "Candle.InvertedHammer", + "Candle.Kicking.Bearish", + "Candle.Kicking.Bullish", + "Candle.LongShadow.Lower", + "Candle.LongShadow.Upper", + "Candle.Marubozu.Black", + "Candle.Marubozu.White", + "Candle.MorningStar", + "Candle.ShootingStar", + "Candle.SpinningTop.Black", + "Candle.SpinningTop.White", + "Candle.3BlackCrows", + "Candle.3WhiteSoldiers", + "Candle.TriStar.Bearish", + "Candle.TriStar.Bullish", + "change_abs", + "change_from_open", + "change_from_open_abs", + "volume" + ] +} \ No newline at end of file diff --git a/generate/generate.py b/generate/generate.py index 5de24a9..31c9112 100644 --- a/generate/generate.py +++ b/generate/generate.py @@ -1,17 +1,22 @@ import datetime -import json import re import time import jinja2 +from bs4 import BeautifulSoup from selenium import webdriver -from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import NoSuchElementException, TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from tqdm import tqdm -template = """ +import data + +xpath_column_setup = "/html/body/div[4]/div/div[2]/div[11]" +xpath_filters = "/html/body/div[4]/div/div[2]/div[11]" + +template_field = """ # ---------------------- # Generated file # {{ now() }} @@ -21,6 +26,19 @@ class {{ name }}Field(Field):{% for key, v in enum_values.items() %} {{ key }} = '{{ v.label }}', '{{ v.field_name }}', '{{ v.format }}', {{ v.interval }}, {{ v.historical }}{% endfor %} + +""" +template_filters = """ +# ---------------------- +# Generated file +# {{ now() }} +# ---------------------- +from enum import Enum + + +class {{ name }}(Enum):{% for key, v in enum_values.items() %} + {{ key }} = '{{ v }}'{% endfor %} + """ computed_reco_fields = ['ADX', @@ -77,6 +95,10 @@ def is_recommendation(field_value): return field_value.endswith(' N') or field_value.endswith(' S') or field_value.endswith(' B') +def click_on(driver, xpath): + WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, xpath))).click() + + def get_format(technical_label, field_value): field_type_ = None if "USD" in field_value: @@ -114,7 +136,7 @@ def get_format(technical_label, field_value): return field_type_ -def scrap_columns(url_): +def _start_window(url_): # proxy = Proxy() # proxy.setHttpProxy("https://scanner.tradingview.com/:8080") driver = webdriver.Firefox() # proxy=proxy) @@ -132,14 +154,74 @@ def scrap_columns(url_): driver.switch_to.frame(frame) # Close the Google popup google_closebtn_xpath = '//*[@id="close"]' - WebDriverWait(driver, 1000000).until(EC.element_to_be_clickable((By.XPATH, google_closebtn_xpath))).click() + click_on(driver, google_closebtn_xpath) driver.switch_to.default_content() time.sleep(1) + return driver + + +def get_xpath_filter_field(i): + return f"/html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[{i}]/div[2]/div/span" + + +def get_xpath_field_name(i): + return f"/html/body/div[10]/div/div/div/div[3]/div[1]/div/div/div[{i}]/div[1]" + + +def get_xpath_filter_value(i): + return f"/html/body/div[10]/div/div/div/div[4]/div/div[1]/div[{i}]/label/span" + + +def get_field_values(driver): + fields = driver.find_element_by_xpath("/html/body/div[10]/div/div/div/div[4]/div/div[1]") + innerHTML = fields.get_attribute('innerHTML') + + soup = BeautifulSoup(innerHTML, "html.parser") + # get all the spans + spans = soup.find_all("span", class_="tv-control-checkbox__label") + fields_values = [span.text for span in spans] + return fields_values - # Open the filter popup - filter_popup_xpath = "/html/body/div[4]/div/div[3]/div/div[1]" - WebDriverWait(driver, 1000000).until(EC.element_to_be_clickable((By.XPATH, filter_popup_xpath))).click() + +def scrap_field_values(url_): + driver = _start_window(url_) + click_on(driver, xpath_filters) + reset_all = "/html/body/div[10]/div/div/div/div[2]/div" + click_on(driver, reset_all) + + fields = {} + for i in range(1, 10000): + xpath_field_name = get_xpath_field_name(i) + print("Search field on xpath: ", xpath_field_name, "...") + try: + field_name = driver.find_element_by_xpath(xpath_field_name).text + except NoSuchElementException as e: + break + + if field_name is None or field_name == "": + break + + xpath_field = get_xpath_filter_field(i) + + try: + click_on(driver, xpath_field) + fields_values = get_field_values(driver) + fields[field_name] = fields_values + except TimeoutException: + print("TimeoutException on field: ", field_name) + continue + except NoSuchElementException: + print("NoSuchElementException on field: ", field_name) + continue + + driver.quit() + return fields + + +def scrap_columns(url_): + driver = _start_window(url_) + click_on(driver, xpath_column_setup) fields_attribute = {} # Check all the columns @@ -204,7 +286,7 @@ def format_field(field: str): elif field[0].isdigit(): field = f'{field[1:]}_{field[0]}' # Remove - field = remove(field, ['(', ')', ',', '/', '-']) + field = remove(field, ['(', ')', ',', '/', '-', ':']) field = field.strip() # Replace field = (field.replace(' ', '_') @@ -252,24 +334,31 @@ def set_intervals(columns): def fill_template(name, columns): # Render the template - template_code = jinja2.Template(template) + template_code = jinja2.Template(template_field) template_code.globals['now'] = datetime.datetime.utcnow return template_code.render(name=name, enum_values=columns) +def fill_filter_template(classname, columns): + # Render the template + template_code = jinja2.Template(template_filters) + template_code.globals['now'] = datetime.datetime.utcnow + return template_code.render(name=classname, enum_values=columns) + + def load_intervals(): - with open('time_intervals.json') as f: - return json.load(f)['columns'] + with open('data/time_intervals.json') as f: + return data.load(f)['columns'] def load_patterns(): - with open('patterns.json') as f: - return json.load(f)['patterns'] + with open('data/patterns.json') as f: + return data.load(f)['patterns'] def load_main(): - with open('main.json') as f: - return json.load(f)['main'] + with open('data/main.json') as f: + return data.load(f)['main'] def add_patterns_columns(columns): @@ -300,6 +389,14 @@ def add_main_columns(columns): return columns +def generate_filter_columns(values): + newdic = {} + for value in values: + if value != 'Any': + newdic[format_field(value)] = value + return newdic + + def generate_columns(selenium_columns): selenium_columns = add_main_columns(selenium_columns) selenium_columns = add_patterns_columns(selenium_columns) @@ -309,5 +406,5 @@ def generate_columns(selenium_columns): def write(filename, generated_template): - with open(f'../tvscreener/field/{filename}.py', 'w') as fp: + with open(f'code/{filename}.py.generated', 'w') as fp: fp.write(generated_template) diff --git a/generate/main.json b/generate/main.json deleted file mode 100644 index 6836bac..0000000 --- a/generate/main.json +++ /dev/null @@ -1,2 +0,0 @@ -{"main": ["logoid", "name", "description", "type", "subtype", "currency", -"fundamental_currency_code"]} \ No newline at end of file diff --git a/generate/patterns.json b/generate/patterns.json deleted file mode 100644 index e25cb04..0000000 --- a/generate/patterns.json +++ /dev/null @@ -1,29 +0,0 @@ -{ "patterns": [ - "Candle.AbandonedBaby.Bearish", - "Candle.AbandonedBaby.Bullish", - "Candle.Engulfing.Bearish", - "Candle.Harami.Bearish", - "Candle.Engulfing.Bullish", - "Candle.Harami.Bullish", - "Candle.Doji", - "Candle.Doji.Dragonfly", - "Candle.EveningStar", - "Candle.Doji.Gravestone", - "Candle.Hammer", - "Candle.HangingMan", - "Candle.InvertedHammer", - "Candle.Kicking.Bearish", - "Candle.Kicking.Bullish", - "Candle.LongShadow.Lower", - "Candle.LongShadow.Upper", - "Candle.Marubozu.Black", - "Candle.Marubozu.White", - "Candle.MorningStar", - "Candle.ShootingStar", - "Candle.SpinningTop.Black", - "Candle.SpinningTop.White", - "Candle.3BlackCrows", - "Candle.3WhiteSoldiers", - "Candle.TriStar.Bearish", - "Candle.TriStar.Bullish" -]} \ No newline at end of file diff --git a/generate/time_intervals.json b/generate/time_intervals.json deleted file mode 100644 index 421065f..0000000 --- a/generate/time_intervals.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "columns": [ - "ADR", - "ADX", - "ADX+DI", - "ADX-DI", - "AO", - "ATR", - "Aroon.Down", - "Aroon.Up", - "BB.lower", - "BB.upper", - "BBPower", - "CCI20", - "DonchCh20.Lower", - "DonchCh20.Upper", - "EMA10", - "EMA100", - "EMA20", - "EMA200", - "EMA30", - "EMA5", - "EMA50", - "HullMA9", - "Ichimoku.BLine", - "Ichimoku.CLine", - "Ichimoku.Lead1", - "Ichimoku.Lead2", - "KltChnl.lower", - "KltChnl.upper", - "MACD.macd", - "MACD.signal", - "Mom", - "P.SAR", - "Pivot.M.Camarilla.Middle", - "Pivot.M.Camarilla.R1", - "Pivot.M.Camarilla.R2", - "Pivot.M.Camarilla.R3", - "Pivot.M.Camarilla.S1", - "Pivot.M.Camarilla.S2", - "Pivot.M.Camarilla.S3", - "Pivot.M.Classic.Middle", - "Pivot.M.Classic.R1", - "Pivot.M.Classic.R2", - "Pivot.M.Classic.R3", - "Pivot.M.Classic.S1", - "Pivot.M.Classic.S2", - "Pivot.M.Classic.S3", - "Pivot.M.Demark.Middle", - "Pivot.M.Demark.R1", - "Pivot.M.Demark.S1", - "Pivot.M.Fibonacci.Middle", - "Pivot.M.Fibonacci.R1", - "Pivot.M.Fibonacci.R2", - "Pivot.M.Fibonacci.R3", - "Pivot.M.Fibonacci.S1", - "Pivot.M.Fibonacci.S2", - "Pivot.M.Fibonacci.S3", - "Pivot.M.Woodie.Middle", - "Pivot.M.Woodie.R1", - "Pivot.M.Woodie.R2", - "Pivot.M.Woodie.R3", - "Pivot.M.Woodie.S1", - "Pivot.M.Woodie.S2", - "Pivot.M.Woodie.S3", - "ROC", - "RSI", - "RSI7", - "Recommend.All", - "Recommend.MA", - "Recommend.Other", - "SMA10", - "SMA100", - "SMA20", - "SMA200", - "SMA30", - "SMA5", - "SMA50", - "Stoch.D", - "Stoch.K", - "Stoch.RSI.D", - "Stoch.RSI.K", - "UO", - "VWAP", - "VWMA", - "W.R", - "change", - "close", - "gap", - "high", - "low", - "open", - "MoneyFlow", - "Value.Traded", - "relative_volume_10d_calc", - "candlestick", - "Candle.AbandonedBaby.Bearish", - "Candle.AbandonedBaby.Bullish", - "Candle.Engulfing.Bearish", - "Candle.Harami.Bearish", - "Candle.Engulfing.Bullish", - "Candle.Harami.Bullish", - "Candle.Doji", - "Candle.Doji.Dragonfly", - "Candle.EveningStar", - "Candle.Doji.Gravestone", - "Candle.Hammer", - "Candle.HangingMan", - "Candle.InvertedHammer", - "Candle.Kicking.Bearish", - "Candle.Kicking.Bullish", - "Candle.LongShadow.Lower", - "Candle.LongShadow.Upper", - "Candle.Marubozu.Black", - "Candle.Marubozu.White", - "Candle.MorningStar", - "Candle.ShootingStar", - "Candle.SpinningTop.Black", - "Candle.SpinningTop.White", - "Candle.3BlackCrows", - "Candle.3WhiteSoldiers", - "Candle.TriStar.Bearish", - "Candle.TriStar.Bullish", - "change_abs", - "change_from_open", - "change_from_open_abs", - "volume" - ] -} \ No newline at end of file diff --git a/test/functional/test_forexscreener.py b/test/functional/test_forexscreener.py index e370516..55b9c5b 100644 --- a/test/functional/test_forexscreener.py +++ b/test/functional/test_forexscreener.py @@ -1,6 +1,7 @@ import unittest -from tvscreener import ForexScreener, TimeInterval, Region, ForexField, FilterOperator +from tvscreener import ForexScreener, TimeInterval, ForexField, FilterOperator +from tvscreener.field import Region class TestForexScreener(unittest.TestCase): diff --git a/test/functional/test_stockscreener.py b/test/functional/test_stockscreener.py index 443913f..b6ed2d8 100644 --- a/test/functional/test_stockscreener.py +++ b/test/functional/test_stockscreener.py @@ -4,8 +4,9 @@ import pandas as pd -from tvscreener import StockScreener, TimeInterval, SymbolType, SubMarket, Country, Exchange, MalformedRequestException, \ - ExtraFilter, FilterOperator, StocksMarket, StockField +from tvscreener import StockScreener, TimeInterval, MalformedRequestException, \ + ExtraFilter, FilterOperator, StockField +from tvscreener.field import SymbolType, Market, SubMarket, Country, Exchange class TestScreener(unittest.TestCase): @@ -37,7 +38,7 @@ def test_search(self): ss.set_symbol_types(SymbolType.COMMON_STOCK) ss.search('AA') df = ss.get() - self.assertEqual(102, len(df)) + self.assertGreater(len(df), 80) self.assertEqual(df.loc[0, "Symbol"], "NASDAQ:AAPL") self.assertEqual(df.loc[0, "Name"], "AAPL") @@ -102,12 +103,13 @@ def test_primary_filter(self): def test_market(self): ss = StockScreener() - ss.set_markets(StocksMarket.ARGENTINA) + ss.set_markets(Market.ARGENTINA) df = ss.get() self.assertEqual(150, len(df)) - self.assertEqual("BCBA:AAPL", df.loc[0, "Symbol"], ) - self.assertEqual("AAPL", df.loc[0, "Name"]) + # WARNING: Order is not guaranteed + self.assertIn("BCBA:AA", df.loc[0, "Symbol"], ) + self.assertIn("AA", df.loc[0, "Name"]) def test_submarket(self): ss = StockScreener() @@ -124,8 +126,9 @@ def test_submarket_pink(self): df = ss.get() self.assertEqual(150, len(df)) - self.assertEqual("OTC:LVMHF", df.loc[0, "Symbol"]) - self.assertEqual("LVMHF", df.loc[0, "Name"]) + # WARNING: Order is not guaranteed + self.assertIn("OTC:LVM", df.loc[0, "Symbol"]) + self.assertIn("LVM", df.loc[0, "Name"]) def test_country(self): ss = StockScreener() diff --git a/test/unit/test_fields.py b/test/unit/test_fields.py index 192a902..b0f007d 100644 --- a/test/unit/test_fields.py +++ b/test/unit/test_fields.py @@ -29,7 +29,8 @@ def test_rec_label(self): self.assertEqual(None, StockField.AVERAGE_DIRECTIONAL_INDEX_14.get_rec_label()) self.assertEqual("Reco. Bull Bear Power", StockField.BULL_BEAR_POWER.get_rec_label()) self.assertEqual("Reco. Hull Moving Average (9)", StockField.HULL_MOVING_AVERAGE_9.get_rec_label()) - self.assertEqual("Reco. Ultimate Oscillator (7, 14, 28)", StockField.ULTIMATE_OSCILLATOR_7_14_28.get_rec_label()) + self.assertEqual("Reco. Ultimate Oscillator (7, 14, 28)", + StockField.ULTIMATE_OSCILLATOR_7_14_28.get_rec_label()) def test_get_by_label(self): self.assertEqual(StockField.VOLUME, StockField.get_by_label(StockField, StockField.VOLUME.label)) diff --git a/test/unit/test_filters.py b/test/unit/test_filters.py index a8233df..bab4484 100644 --- a/test/unit/test_filters.py +++ b/test/unit/test_filters.py @@ -1,25 +1,24 @@ import unittest -from tvscreener import StockScreener, Type, ExtraFilter, SymbolType, FilterOperator, SubMarket, StocksMarket, \ - ForexScreener, StockField, ForexField -from tvscreener.filter import Country, Exchange, Rating, Region +from tvscreener import StockScreener, ExtraFilter, FilterOperator, ForexScreener, StockField, ForexField +from tvscreener.field import Market, Country, Exchange, Rating, SymbolType, Type, SubMarket, Region class TestStockFilters(unittest.TestCase): def test_set_markets(self): ss = StockScreener() - ss.set_markets(StocksMarket.JAPAN, StocksMarket.FRANCE) - self.assertEqual([StocksMarket.JAPAN, StocksMarket.FRANCE], ss.markets) + ss.set_markets(Market.JAPAN, Market.FRANCE) + self.assertEqual([Market.JAPAN, Market.FRANCE], ss.markets) def test_set_markets_unique(self): ss = StockScreener() - ss.set_markets(StocksMarket.JAPAN) - self.assertEqual([StocksMarket.JAPAN], ss.markets) + ss.set_markets(Market.JAPAN) + self.assertEqual([Market.JAPAN], ss.markets) def test_set_markets_all(self): ss = StockScreener() - ss.set_markets(StocksMarket.ALL) - self.assertEqual([m for m in StocksMarket], ss.markets) + ss.set_markets(Market.ALL) + self.assertEqual([m for m in Market], ss.markets) def test_stock_additional_subtypes(self): ss = StockScreener() @@ -226,10 +225,10 @@ def test_exchanges(self): self.assertEqual(Exchange.NYSE, exchange.values[1]) def test_stockmarket_names(self): - self.assertIn("GREECE", StocksMarket.names()) + self.assertIn("GREECE", Market.names()) def test_stockmarket_values(self): - self.assertIn("venezuela", StocksMarket.values()) + self.assertIn("venezuela", Market.values()) def test_rating(self): self.assertIn(0.63, Rating.STRONG_BUY) diff --git a/tvscreener/__init__.py b/tvscreener/__init__.py index c00f0e2..576d209 100644 --- a/tvscreener/__init__.py +++ b/tvscreener/__init__.py @@ -4,16 +4,15 @@ import pandas as pd import requests -from tvscreener.field import TimeInterval, Field +from tvscreener.field import TimeInterval, Field, Market, Type, SymbolType from tvscreener.field.crypto import CryptoField from tvscreener.field.forex import ForexField from tvscreener.field.stock import StockField -from tvscreener.filter import FilterOperator, Filter, Rating, StocksMarket, ExtraFilter, SymbolType, Type, SubMarket, \ - Country, Exchange, Region +from tvscreener.filter import FilterOperator, Filter, ExtraFilter from tvscreener.util import get_columns_to_request, is_status_code_ok, get_url, millify, get_recommendation, \ MalformedRequestException -default_market = StocksMarket.AMERICA +default_market = Market.AMERICA default_min_range = 0 default_max_range = 150 default_sort_stocks = StockField.MARKET_CAPITALIZATION @@ -214,14 +213,14 @@ def set_symbol_types(self, *symbol_types: SymbolType): for symbol_type in symbol_types: self.add_filter(StockField.SUBTYPE, FilterOperator.IN_RANGE, symbol_type.value.copy()) - def set_markets(self, *markets: StocksMarket): + def set_markets(self, *markets: Market): """ Set the markets to be scanned :param markets: list of markets :return: None """ - if StocksMarket.ALL in markets: - self.markets = [market for market in StocksMarket] + if Market.ALL in markets: + self.markets = [market for market in Market] else: self.markets = [market for market in markets] diff --git a/tvscreener/beauty/__init__.py b/tvscreener/beauty.py similarity index 100% rename from tvscreener/beauty/__init__.py rename to tvscreener/beauty.py diff --git a/tvscreener/field/__init__.py b/tvscreener/field/__init__.py index 2a7e0ea..2cae0c2 100644 --- a/tvscreener/field/__init__.py +++ b/tvscreener/field/__init__.py @@ -1,21 +1,7 @@ +import math from enum import Enum -class TimeInterval(Enum): - ONE_MINUTE = "1" - FIVE_MINUTES = "5" - FIFTEEN_MINUTES = "15" - THIRTY_MINUTES = "30" - SIXTY_MINUTES = "60" - TWO_HOURS = "120" - FOUR_HOURS = "240" - ONE_DAY = "1D" - ONE_WEEK = "1W" - - def update_mode(self): - return f"update_mode|{self.value}" - - def add_time_interval(field_name, time_interval): return f"{field_name}|{time_interval.value}" @@ -61,3 +47,457 @@ def get_by_label(cls, specific_fields, label): return None +class Type(Enum): + STOCK = "stock" + DEPOSITORY_RECEIPT = "dr" + FUND = "fund" + STRUCTURED = "structured" + + +class Rating(Enum): + STRONG_BUY = 0.5, 1, "Strong Buy" + BUY = 0.1, 0.5, "Buy" + NEUTRAL = -0.1, 0.1, "Neutral" + SELL = -0.5, -0.1, "Sell" + STRONG_SELL = -1, -0.5, "Strong Sell" + UNKNOWN = math.nan, math.nan, "Unknown" + + def __init__(self, min_, max_, label): + self.min = min_ + self.max = max_ + self.label = label + + def __contains__(self, item): + return self.min <= item <= self.max + + def range(self): + return [self.min, self.max] + + @classmethod + def find(cls, value: float): + if value is not None: + for rating in Rating: + if value in rating: + return rating + return Rating.UNKNOWN + + @classmethod + def names(cls): + return list(map(lambda c: c.name, cls)) + + @classmethod + def values(cls): + return list(map(lambda c: c.value, cls)) + + +class TimeInterval(Enum): + ONE_MINUTE = "1" + FIVE_MINUTES = "5" + FIFTEEN_MINUTES = "15" + THIRTY_MINUTES = "30" + SIXTY_MINUTES = "60" + TWO_HOURS = "120" + FOUR_HOURS = "240" + ONE_DAY = "1D" + ONE_WEEK = "1W" + + def update_mode(self): + return f"update_mode|{self.value}" + + +class Country(Enum): + ALBANIA = 'Albania' + ARGENTINA = 'Argentina' + AUSTRALIA = 'Australia' + AUSTRIA = 'Austria' + AZERBAIJAN = 'Azerbaijan' + BAHAMAS = 'Bahamas' + BARBADOS = 'Barbados' + BELGIUM = 'Belgium' + BERMUDA = 'Bermuda' + BRAZIL = 'Brazil' + BRITISH_VIRGIN_ISLANDS = 'British Virgin Islands' + CAMBODIA = 'Cambodia' + CANADA = 'Canada' + CAYMAN_ISLANDS = 'Cayman Islands' + CHILE = 'Chile' + CHINA = 'China' + COLOMBIA = 'Colombia' + COSTA_RICA = 'Costa Rica' + CYPRUS = 'Cyprus' + CZECH_REPUBLIC = 'Czech Republic' + DENMARK = 'Denmark' + DOMINICAN_REPUBLIC = 'Dominican Republic' + EGYPT = 'Egypt' + FAROE_ISLANDS = 'Faroe Islands' + FINLAND = 'Finland' + FRANCE = 'France' + GERMANY = 'Germany' + GIBRALTAR = 'Gibraltar' + GREECE = 'Greece' + HONG_KONG = 'Hong Kong' + HUNGARY = 'Hungary' + ICELAND = 'Iceland' + INDIA = 'India' + INDONESIA = 'Indonesia' + IRELAND = 'Ireland' + ISRAEL = 'Israel' + ITALY = 'Italy' + JAMAICA = 'Jamaica' + JAPAN = 'Japan' + JORDAN = 'Jordan' + KAZAKHSTAN = 'Kazakhstan' + LUXEMBOURG = 'Luxembourg' + MACAU = 'Macau' + MACEDONIA = 'Macedonia' + MALAYSIA = 'Malaysia' + MALTA = 'Malta' + MAURITIUS = 'Mauritius' + MEXICO = 'Mexico' + MONACO = 'Monaco' + MONGOLIA = 'Mongolia' + MONTENEGRO = 'Montenegro' + NETHERLANDS = 'Netherlands' + NEW_ZEALAND = 'New Zealand' + NORWAY = 'Norway' + PANAMA = 'Panama' + PERU = 'Peru' + PHILIPPINES = 'Philippines' + POLAND = 'Poland' + PORTUGAL = 'Portugal' + PUERTO_RICO = 'Puerto Rico' + ROMANIA = 'Romania' + RUSSIAN_FEDERATION = 'Russian Federation' + SINGAPORE = 'Singapore' + SOUTH_AFRICA = 'South Africa' + SOUTH_KOREA = 'South Korea' + SPAIN = 'Spain' + SWEDEN = 'Sweden' + SWITZERLAND = 'Switzerland' + TAIWAN = 'Taiwan' + TANZANIA = 'Tanzania' + THAILAND = 'Thailand' + TURKEY = 'Turkey' + U_S__VIRGIN_ISLANDS = 'U.S. Virgin Islands' + UNITED_ARAB_EMIRATES = 'United Arab Emirates' + UNITED_KINGDOM = 'United Kingdom' + UNITED_STATES = 'United States' + URUGUAY = 'Uruguay' + VIETNAM = 'Vietnam' + + +class Exchange(Enum): + OTC = "OTC" + NYSE_ARCA = "AMEX" + NASDAQ = "NASDAQ" + NYSE = "NYSE" + + +class Index(Enum): + DOW_JONES_COMPOSITE_AVERAGE = 'Dow Jones Composite Average' + DOW_JONES_INDUSTRIAL_AVERAGE = 'Dow Jones Industrial Average' + DOW_JONES_TRANSPORTATION_AVERAGE = 'Dow Jones Transportation Average' + DOW_JONES_UTILITY_AVERAGE = 'Dow Jones Utility Average' + KBW_NASDAQ_BANK_INDEX = 'KBW NASDAQ BANK INDEX' + MINI_RUSSELL_2000_INDEX = 'MINI RUSSELL 2000 INDEX' + NASDAQ_100 = 'NASDAQ 100' + NASDAQ_100_TECHNOLOGY_SECTOR = 'NASDAQ 100 TECHNOLOGY SECTOR' + NASDAQ_BANK = 'NASDAQ BANK' + NASDAQ_BIOTECHNOLOGY = 'NASDAQ BIOTECHNOLOGY' + NASDAQ_COMPOSITE = 'NASDAQ COMPOSITE' + NASDAQ_COMPUTER = 'NASDAQ COMPUTER' + NASDAQ_GOLDEN_DRAGON_CHINA_INDEX = 'NASDAQ GOLDEN DRAGON CHINA INDEX' + NASDAQ_INDUSTRIAL = 'NASDAQ INDUSTRIAL' + NASDAQ_INSURANCE = 'NASDAQ INSURANCE' + NASDAQ_OTHER_FINANCE = 'NASDAQ OTHER FINANCE' + NASDAQ_TELECOMMUNICATIONS = 'NASDAQ TELECOMMUNICATIONS' + NASDAQ_TRANSPORTATION = 'NASDAQ TRANSPORTATION' + NASDAQ_US_BENCHMARK_FOOD_PRODUCERS_INDEX = 'NASDAQ US BENCHMARK FOOD PRODUCERS INDEX' + NYSE_ARCA_MAJOR_MARKET = 'NYSE ARCA MAJOR MARKET' + PHLX_GOLD_AND_SILVER_SECTOR_INDEX = 'PHLX GOLD AND SILVER SECTOR INDEX' + PHLX_HOUSING_SECTOR = 'PHLX HOUSING SECTOR' + PHLX_OIL_SERVICE_SECTOR = 'PHLX OIL SERVICE SECTOR' + PHLX_SEMICONDUCTOR = 'PHLX SEMICONDUCTOR' + PHLX_UTILITY_SECTOR = 'PHLX UTILITY SECTOR' + RUSSELL_1000 = 'RUSSELL 1000' + RUSSELL_2000 = 'RUSSELL 2000' + RUSSELL_3000 = 'RUSSELL 3000' + SANDP_100 = 'S&P 100' + SANDP_400 = 'S&P 400' + SANDP_500 = 'S&P 500' + SANDP_500_COMMUNICATION_SERVICES = 'S&P 500 Communication Services' + SANDP_500_CONSUMER_DISCRETIONARY = 'S&P 500 Consumer Discretionary' + SANDP_500_CONSUMER_STAPLES = 'S&P 500 Consumer Staples' + SANDP_500_ESG_INDEX = 'S&P 500 ESG INDEX' + SANDP_500_ENERGY = 'S&P 500 Energy' + SANDP_500_FINANCIALS = 'S&P 500 Financials' + SANDP_500_HEALTH_CARE = 'S&P 500 Health Care' + SANDP_500_INDUSTRIALS = 'S&P 500 Industrials' + SANDP_500_INFORMATION_TECHNOLOGY = 'S&P 500 Information Technology' + SANDP_500_MATERIALS = 'S&P 500 Materials' + SANDP_500_REAL_ESTATE = 'S&P 500 Real Estate' + SANDP_500_UTILITIES = 'S&P 500 Utilities' + + +class Industry(Enum): + ADVERTISINGMARKETING_SERVICES = 'Advertising/Marketing Services' + AEROSPACE_AND_DEFENSE = 'Aerospace & Defense' + AGRICULTURAL_COMMODITIESMILLING = 'Agricultural Commodities/Milling' + AIR_FREIGHTCOURIERS = 'Air Freight/Couriers' + AIRLINES = 'Airlines' + ALTERNATIVE_POWER_GENERATION = 'Alternative Power Generation' + ALUMINUM = 'Aluminum' + APPARELFOOTWEAR = 'Apparel/Footwear' + APPARELFOOTWEAR_RETAIL = 'Apparel/Footwear Retail' + AUTO_PARTS_OEM = 'Auto Parts: OEM' + AUTOMOTIVE_AFTERMARKET = 'Automotive Aftermarket' + BEVERAGES_ALCOHOLIC = 'Beverages: Alcoholic' + BEVERAGES_NONALCOHOLIC = 'Beverages: Non-Alcoholic' + BIOTECHNOLOGY = 'Biotechnology' + BROADCASTING = 'Broadcasting' + BUILDING_PRODUCTS = 'Building Products' + CABLESATELLITE_TV = 'Cable/Satellite TV' + CASINOSGAMING = 'Casinos/Gaming' + CATALOGSPECIALTY_DISTRIBUTION = 'Catalog/Specialty Distribution' + CHEMICALS_AGRICULTURAL = 'Chemicals: Agricultural' + CHEMICALS_MAJOR_DIVERSIFIED = 'Chemicals: Major Diversified' + CHEMICALS_SPECIALTY = 'Chemicals: Specialty' + COAL = 'Coal' + COMMERCIAL_PRINTINGFORMS = 'Commercial Printing/Forms' + COMPUTER_COMMUNICATIONS = 'Computer Communications' + COMPUTER_PERIPHERALS = 'Computer Peripherals' + COMPUTER_PROCESSING_HARDWARE = 'Computer Processing Hardware' + CONSTRUCTION_MATERIALS = 'Construction Materials' + CONSUMER_SUNDRIES = 'Consumer Sundries' + CONTAINERSPACKAGING = 'Containers/Packaging' + CONTRACT_DRILLING = 'Contract Drilling' + DATA_PROCESSING_SERVICES = 'Data Processing Services' + DEPARTMENT_STORES = 'Department Stores' + DISCOUNT_STORES = 'Discount Stores' + DRUGSTORE_CHAINS = 'Drugstore Chains' + ELECTRIC_UTILITIES = 'Electric Utilities' + ELECTRICAL_PRODUCTS = 'Electrical Products' + ELECTRONIC_COMPONENTS = 'Electronic Components' + ELECTRONIC_EQUIPMENTINSTRUMENTS = 'Electronic Equipment/Instruments' + ELECTRONIC_PRODUCTION_EQUIPMENT = 'Electronic Production Equipment' + ELECTRONICS_DISTRIBUTORS = 'Electronics Distributors' + ELECTRONICSAPPLIANCE_STORES = 'Electronics/Appliance Stores' + ELECTRONICSAPPLIANCES = 'Electronics/Appliances' + ENGINEERING_AND_CONSTRUCTION = 'Engineering & Construction' + ENVIRONMENTAL_SERVICES = 'Environmental Services' + FINANCERENTALLEASING = 'Finance/Rental/Leasing' + FINANCIAL_CONGLOMERATES = 'Financial Conglomerates' + FINANCIAL_PUBLISHINGSERVICES = 'Financial Publishing/Services' + FOOD_DISTRIBUTORS = 'Food Distributors' + FOOD_RETAIL = 'Food Retail' + FOOD_MAJOR_DIVERSIFIED = 'Food: Major Diversified' + FOOD_MEATFISHDAIRY = 'Food: Meat/Fish/Dairy' + FOOD_SPECIALTYCANDY = 'Food: Specialty/Candy' + FOREST_PRODUCTS = 'Forest Products' + GAS_DISTRIBUTORS = 'Gas Distributors' + GENERAL_GOVERNMENT = 'General Government' + HOME_FURNISHINGS = 'Home Furnishings' + HOME_IMPROVEMENT_CHAINS = 'Home Improvement Chains' + HOMEBUILDING = 'Homebuilding' + HOSPITALNURSING_MANAGEMENT = 'Hospital/Nursing Management' + HOTELSRESORTSCRUISE_LINES = 'Hotels/Resorts/Cruise lines' + HOUSEHOLDPERSONAL_CARE = 'Household/Personal Care' + INDUSTRIAL_CONGLOMERATES = 'Industrial Conglomerates' + INDUSTRIAL_MACHINERY = 'Industrial Machinery' + INDUSTRIAL_SPECIALTIES = 'Industrial Specialties' + INFORMATION_TECHNOLOGY_SERVICES = 'Information Technology Services' + INSURANCE_BROKERSSERVICES = 'Insurance Brokers/Services' + INTEGRATED_OIL = 'Integrated Oil' + INTERNET_RETAIL = 'Internet Retail' + INTERNET_SOFTWARESERVICES = 'Internet Software/Services' + INVESTMENT_BANKSBROKERS = 'Investment Banks/Brokers' + INVESTMENT_MANAGERS = 'Investment Managers' + INVESTMENT_TRUSTSMUTUAL_FUNDS = 'Investment Trusts/Mutual Funds' + LIFEHEALTH_INSURANCE = 'Life/Health Insurance' + MAJOR_BANKS = 'Major Banks' + MAJOR_TELECOMMUNICATIONS = 'Major Telecommunications' + MANAGED_HEALTH_CARE = 'Managed Health Care' + MARINE_SHIPPING = 'Marine Shipping' + MEDIA_CONGLOMERATES = 'Media Conglomerates' + MEDICAL_DISTRIBUTORS = 'Medical Distributors' + MEDICAL_SPECIALTIES = 'Medical Specialties' + MEDICALNURSING_SERVICES = 'Medical/Nursing Services' + METAL_FABRICATION = 'Metal Fabrication' + MISCELLANEOUS = 'Miscellaneous' + MISCELLANEOUS_COMMERCIAL_SERVICES = 'Miscellaneous Commercial Services' + MISCELLANEOUS_MANUFACTURING = 'Miscellaneous Manufacturing' + MOTOR_VEHICLES = 'Motor Vehicles' + MOVIESENTERTAINMENT = 'Movies/Entertainment' + MULTILINE_INSURANCE = 'Multi-Line Insurance' + OFFICE_EQUIPMENTSUPPLIES = 'Office Equipment/Supplies' + OIL_AND_GAS_PIPELINES = 'Oil & Gas Pipelines' + OIL_AND_GAS_PRODUCTION = 'Oil & Gas Production' + OIL_REFININGMARKETING = 'Oil Refining/Marketing' + OILFIELD_SERVICESEQUIPMENT = 'Oilfield Services/Equipment' + OTHER_CONSUMER_SERVICES = 'Other Consumer Services' + OTHER_CONSUMER_SPECIALTIES = 'Other Consumer Specialties' + OTHER_METALSMINERALS = 'Other Metals/Minerals' + OTHER_TRANSPORTATION = 'Other Transportation' + PACKAGED_SOFTWARE = 'Packaged Software' + PERSONNEL_SERVICES = 'Personnel Services' + PHARMACEUTICALS_GENERIC = 'Pharmaceuticals: Generic' + PHARMACEUTICALS_MAJOR = 'Pharmaceuticals: Major' + PHARMACEUTICALS_OTHER = 'Pharmaceuticals: Other' + PRECIOUS_METALS = 'Precious Metals' + PROPERTYCASUALTY_INSURANCE = 'Property/Casualty Insurance' + PUBLISHING_BOOKSMAGAZINES = 'Publishing: Books/Magazines' + PUBLISHING_NEWSPAPERS = 'Publishing: Newspapers' + PULP_AND_PAPER = 'Pulp & Paper' + RAILROADS = 'Railroads' + REAL_ESTATE_DEVELOPMENT = 'Real Estate Development' + REAL_ESTATE_INVESTMENT_TRUSTS = 'Real Estate Investment Trusts' + RECREATIONAL_PRODUCTS = 'Recreational Products' + REGIONAL_BANKS = 'Regional Banks' + RESTAURANTS = 'Restaurants' + SAVINGS_BANKS = 'Savings Banks' + SEMICONDUCTORS = 'Semiconductors' + SERVICES_TO_THE_HEALTH_INDUSTRY = 'Services to the Health Industry' + SPECIALTY_INSURANCE = 'Specialty Insurance' + SPECIALTY_STORES = 'Specialty Stores' + SPECIALTY_TELECOMMUNICATIONS = 'Specialty Telecommunications' + STEEL = 'Steel' + TELECOMMUNICATIONS_EQUIPMENT = 'Telecommunications Equipment' + TEXTILES = 'Textiles' + TOBACCO = 'Tobacco' + TOOLS_AND_HARDWARE = 'Tools & Hardware' + TRUCKING = 'Trucking' + TRUCKSCONSTRUCTIONFARM_MACHINERY = 'Trucks/Construction/Farm Machinery' + WATER_UTILITIES = 'Water Utilities' + WHOLESALE_DISTRIBUTORS = 'Wholesale Distributors' + WIRELESS_TELECOMMUNICATIONS = 'Wireless Telecommunications' + + +class Sector(Enum): + ANY = "Any" + COMMERCIAL_SERVICES = "Commercial Services" + COMMUNICATIONS = "Communications" + CONSUMER_DURABLES = "Consumer Durables" + CONSUMER_NON_DURABLES = "Consumer Non-Durables" + CONSUMER_SERVICES = "Consumer Services" + DISTRIBUTION_SERVICES = "Distribution Services" + ELECTRONIC_TECHNOLOGY = "Electronic Technology" + ENERGY_MINERALS = "Energy Minerals" + FINANCE = "Finance" + GOVERNMENT = "Government" + HEALTH_SERVICES = "Health Services" + HEALTH_TECHNOLOGY = "Health Technology" + INDUSTRIAL_SERVICES = "Industrial Services" + MISCELLANEOUS = "Miscellaneous" + NON_ENERGY_MINERALS = "Non-Energy Minerals" + PROCESS_INDUSTRIES = "Process Industries" + PRODUCER_MANUFACTURING = "Producer Manufacturing" + RETAIL_TRADE = "Retail Trade" + TECHNOLOGY_SERVICES = "Technology Services" + TRANSPORTATION = "Transportation" + UTILITIES = "Utilities" + + +class Market(Enum): + ALL = "ALL" + AMERICA = "america" + UK = "uk" + INDIA = "india" + SPAIN = "spain" + RUSSIA = "russia" + AUSTRALIA = "australia" + BRAZIL = "brazil" + JAPAN = "japan" + NEWZEALAND = "newzealand" + TURKEY = "turkey" + SWITZERLAND = "switzerland" + HONGKONG = "hongkong" + TAIWAN = "taiwan" + NETHERLANDS = "netherlands" + BELGIUM = "belgium" + PORTUGAL = "portugal" + FRANCE = "france" + MEXICO = "mexico" + CANADA = "canada" + COLOMBIA = "colombia" + UAE = "uae" + NIGERIA = "nigeria" + SINGAPORE = "singapore" + GERMANY = "germany" + PAKISTAN = "pakistan" + PERU = "peru" + POLAND = "poland" + ITALY = "italy" + ARGENTINA = "argentina" + ISRAEL = "israel" + EGYPT = "egypt" + SRILANKA = "srilanka" + SERBIA = "serbia" + CHILE = "chile" + CHINA = "china" + MALAYSIA = "malaysia" + MOROCCO = "morocco" + KSA = "ksa" + BAHRAIN = "bahrain" + QATAR = "qatar" + INDONESIA = "indonesia" + FINLAND = "finland" + ICELAND = "iceland" + DENMARK = "denmark" + ROMANIA = "romania" + HUNGARY = "hungary" + SWEDEN = "sweden" + SLOVAKIA = "slovakia" + LITHUANIA = "lithuania" + LUXEMBOURG = "luxembourg" + ESTONIA = "estonia" + LATVIA = "latvia" + VIETNAM = "vietnam" + RSA = "rsa" + THAILAND = "thailand" + TUNISIA = "tunisia" + KOREA = "korea" + KENYA = "kenya" + KUWAIT = "kuwait" + NORWAY = "norway" + PHILIPPINES = "philippines" + GREECE = "greece" + VENEZUELA = "venezuela" + CYPRUS = "cyprus" + BANGLADESH = "bangladesh" + + @classmethod + def names(cls): + return list(map(lambda c: c.name, cls)) + + @classmethod + def values(cls): + return list(map(lambda c: c.value, cls)) + + +class Region(Enum): + AFRICA = "Africa" + AMERICAS = "Americas" + ASIA = "Asia" + EUROPE = "Europe" + MIDDLE_EAST = "Middle East" + PACIFIC = "Pacific" + + +class SubMarket(Enum): + OTCQB = "OTCQB" + OTCQX = "OTCQX" + PINK = "PINK" + + +class SymbolType(Enum): + CLOSED_END_FUND = ["closedend"] + COMMON_STOCK = ["common"] + DEPOSITORY_RECEIPT = ["foreign-issuer"] + ETF = ["etf", "etf,odd", "etf,otc", "etf,cfd"] + ETN = ["etn"] + MUTUAL_FUND = ["mutual"] + PREFERRED_STOCK = ["preferred"] + REIT = ["reit", "reit,cfd", "trust,reit"] + STRUCTURED = [""] # ["SP"] + TRUST_FUND = ["trust"] + UIT = ["unit"] diff --git a/tvscreener/field/crypto.py b/tvscreener/field/crypto.py index 5d5fbe0..840a0eb 100644 --- a/tvscreener/field/crypto.py +++ b/tvscreener/field/crypto.py @@ -1,8 +1,3 @@ - -# ---------------------- -# Generated file -# 2023-08-08 09:09:31.216188 -# ---------------------- from tvscreener.field import Field @@ -186,4 +181,4 @@ class CryptoField(Field): WILLIAMS_PERCENT_RANGE_14 = 'Williams Percent Range (14)', 'W.R', 'computed_recommendation', True, False YEARLY_PERFORMANCE = 'Yearly Performance', 'Perf.Y', 'percent', False, False YTD_PERFORMANCE = 'YTD Performance', 'Perf.YTD', 'percent', False, False - Y_PERFORMANCE_5 = '5Y Performance', 'Perf.5Y', 'percent', False, False \ No newline at end of file + Y_PERFORMANCE_5 = '5Y Performance', 'Perf.5Y', 'percent', False, False diff --git a/tvscreener/field/forex.py b/tvscreener/field/forex.py index b49289f..e3b4894 100644 --- a/tvscreener/field/forex.py +++ b/tvscreener/field/forex.py @@ -1,8 +1,3 @@ - -# ---------------------- -# Generated file -# 2023-08-08 09:09:31.680369 -# ---------------------- from tvscreener.field import Field @@ -173,4 +168,4 @@ class ForexField(Field): WILLIAMS_PERCENT_RANGE_14 = 'Williams Percent Range (14)', 'W.R', 'computed_recommendation', True, False YEARLY_PERFORMANCE = 'Yearly Performance', 'Perf.Y', 'percent', False, False YTD_PERFORMANCE = 'YTD Performance', 'Perf.YTD', 'percent', False, False - Y_PERFORMANCE_5 = '5Y Performance', 'Perf.5Y', 'percent', False, False \ No newline at end of file + Y_PERFORMANCE_5 = '5Y Performance', 'Perf.5Y', 'percent', False, False diff --git a/tvscreener/field/stock.py b/tvscreener/field/stock.py index e921a1d..2a6eb39 100644 --- a/tvscreener/field/stock.py +++ b/tvscreener/field/stock.py @@ -1,8 +1,3 @@ - -# ---------------------- -# Generated file -# 2023-08-08 09:09:30.634904 -# ---------------------- from tvscreener.field import Field @@ -295,4 +290,4 @@ class StockField(Field): YEARLY_PERFORMANCE = 'Yearly Performance', 'Perf.Y', 'percent', False, False YEAR_BETA_1 = '1-Year Beta', 'beta_1_year', 'round', False, False YTD_PERFORMANCE = 'YTD Performance', 'Perf.YTD', 'percent', False, False - Y_PERFORMANCE_5 = '5Y Performance', 'Perf.5Y', 'percent', False, False \ No newline at end of file + Y_PERFORMANCE_5 = '5Y Performance', 'Perf.5Y', 'percent', False, False diff --git a/tvscreener/filter.py b/tvscreener/filter.py new file mode 100644 index 0000000..4ff8fc2 --- /dev/null +++ b/tvscreener/filter.py @@ -0,0 +1,43 @@ +from enum import Enum + +from tvscreener import Field + + +class FilterOperator(Enum): + BELOW = "less" + BELOW_OR_EQUAL = "eless" + ABOVE = "greater" + ABOVE_OR_EQUAL = "egreater" + CROSSES = "crosses" + CROSSES_UP = "crosses_above" + CROSSES_DOWN = "crosses_below" + IN_RANGE = "in_range" + NOT_IN_RANGE = "not_in_range" + EQUAL = "equal" + NOT_EQUAL = "nequal" + MATCH = "match" + + +class ExtraFilter(Enum): + CURRENT_TRADING_DAY = "active_symbol" + SEARCH = "name,description" + PRIMARY = "is_primary" + + def __init__(self, value): + self.field_name = value + + +class Filter: + def __init__(self, field: Field | ExtraFilter, operation: FilterOperator, values): + self.field = field + self.operation = operation + self.values = values if isinstance(values, list) else [values] + + # def name(self): + # return self.field.field_name if isinstance(self.field, Field) else self.field.value + + def to_dict(self): + right = [filter_enum.value if isinstance(filter_enum, Enum) else filter_enum for filter_enum in self.values] + right = right[0] if len(right) == 1 else right + left = self.field.field_name + return {"left": left, "operation": self.operation.value, "right": right} diff --git a/tvscreener/filter/__init__.py b/tvscreener/filter/__init__.py deleted file mode 100644 index 6ced51b..0000000 --- a/tvscreener/filter/__init__.py +++ /dev/null @@ -1,308 +0,0 @@ -import math -from enum import Enum - -from tvscreener import Field - - -class StocksMarket(Enum): - ALL = "ALL" - AMERICA = "america" - UK = "uk" - INDIA = "india" - SPAIN = "spain" - RUSSIA = "russia" - AUSTRALIA = "australia" - BRAZIL = "brazil" - JAPAN = "japan" - NEWZEALAND = "newzealand" - TURKEY = "turkey" - SWITZERLAND = "switzerland" - HONGKONG = "hongkong" - TAIWAN = "taiwan" - NETHERLANDS = "netherlands" - BELGIUM = "belgium" - PORTUGAL = "portugal" - FRANCE = "france" - MEXICO = "mexico" - CANADA = "canada" - COLOMBIA = "colombia" - UAE = "uae" - NIGERIA = "nigeria" - SINGAPORE = "singapore" - GERMANY = "germany" - PAKISTAN = "pakistan" - PERU = "peru" - POLAND = "poland" - ITALY = "italy" - ARGENTINA = "argentina" - ISRAEL = "israel" - EGYPT = "egypt" - SRILANKA = "srilanka" - SERBIA = "serbia" - CHILE = "chile" - CHINA = "china" - MALAYSIA = "malaysia" - MOROCCO = "morocco" - KSA = "ksa" - BAHRAIN = "bahrain" - QATAR = "qatar" - INDONESIA = "indonesia" - FINLAND = "finland" - ICELAND = "iceland" - DENMARK = "denmark" - ROMANIA = "romania" - HUNGARY = "hungary" - SWEDEN = "sweden" - SLOVAKIA = "slovakia" - LITHUANIA = "lithuania" - LUXEMBOURG = "luxembourg" - ESTONIA = "estonia" - LATVIA = "latvia" - VIETNAM = "vietnam" - RSA = "rsa" - THAILAND = "thailand" - TUNISIA = "tunisia" - KOREA = "korea" - KENYA = "kenya" - KUWAIT = "kuwait" - NORWAY = "norway" - PHILIPPINES = "philippines" - GREECE = "greece" - VENEZUELA = "venezuela" - CYPRUS = "cyprus" - BANGLADESH = "bangladesh" - - @classmethod - def names(cls): - return list(map(lambda c: c.name, cls)) - - @classmethod - def values(cls): - return list(map(lambda c: c.value, cls)) - - -class Sector(Enum): - ANY = "Any" - COMMERCIAL_SERVICES = "Commercial Services" - COMMUNICATIONS = "Communications" - CONSUMER_DURABLES = "Consumer Durables" - CONSUMER_NON_DURABLES = "Consumer Non-Durables" - CONSUMER_SERVICES = "Consumer Services" - DISTRIBUTION_SERVICES = "Distribution Services" - ELECTRONIC_TECHNOLOGY = "Electronic Technology" - ENERGY_MINERALS = "Energy Minerals" - FINANCE = "Finance" - GOVERNMENT = "Government" - HEALTH_SERVICES = "Health Services" - HEALTH_TECHNOLOGY = "Health Technology" - INDUSTRIAL_SERVICES = "Industrial Services" - MISCELLANEOUS = "Miscellaneous" - NON_ENERGY_MINERALS = "Non-Energy Minerals" - PROCESS_INDUSTRIES = "Process Industries" - PRODUCER_MANUFACTURING = "Producer Manufacturing" - RETAIL_TRADE = "Retail Trade" - TECHNOLOGY_SERVICES = "Technology Services" - TRANSPORTATION = "Transportation" - UTILITIES = "Utilities" - - -class Country(Enum): - ANY = "Any" - ALBANIA = "Albania" - ARGENTINA = "Argentina" - AUSTRALIA = "Australia" - AUSTRIA = "Austria" - AZERBAIJAN = "Azerbaijan" - BAHAMAS = "Bahamas" - BARBADOS = "Barbados" - BELGIUM = "Belgium" - BERMUDA = "Bermuda" - BRAZIL = "Brazil" - BRITISH_VIRGIN_ISLANDS = "British Virgin Islands" - CAMBODIA = "Cambodia" - CANADA = "Canada" - CAYMAN_ISLANDS = "Cayman Islands" - CHILE = "Chile" - CHINA = "China" - COLOMBIA = "Colombia" - COSTA_RICA = "Costa Rica" - CYPRUS = "Cyprus" - CZECH_REPUBLIC = "Czech Republic" - DENMARK = "Denmark" - DOMINICAN_REPUBLIC = "Dominican Republic" - EGYPT = "Egypt" - FAROE_ISLANDS = "Faroe Islands" - FINLAND = "Finland" - FRANCE = "France" - GERMANY = "Germany" - GIBRALTAR = "Gibraltar" - GREECE = "Greece" - HONG_KONG = "Hong Kong" - HUNGARY = "Hungary" - ICELAND = "Iceland" - INDIA = "India" - INDONESIA = "Indonesia" - IRELAND = "Ireland" - ISRAEL = "Israel" - ITALY = "Italy" - JAMAICA = "Jamaica" - JAPAN = "Japan" - JORDAN = "Jordan" - KAZAKHSTAN = "Kazakhstan" - LUXEMBOURG = "Luxembourg" - MACAU = "Macau" - MACEDONIA = "Macedonia" - MALAYSIA = "Malaysia" - MALTA = "Malta" - MAURITIUS = "Mauritius" - MEXICO = "Mexico" - MONACO = "Monaco" - MONGOLIA = "Mongolia" - MONTENEGRO = "Montenegro" - NETHERLANDS = "Netherlands" - NEW_ZEALAND = "New Zealand" - NORWAY = "Norway" - PANAMA = "Panama" - PAPUA_NEW_GUINEA = "Papua New Guinea" - PERU = "Peru" - PHILIPPINES = "Philippines" - POLAND = "Poland" - PORTUGAL = "Portugal" - PUERTO_RICO = "Puerto Rico" - ROMANIA = "Romania" - RUSSIAN_FEDERATION = "Russian Federation" - SINGAPORE = "Singapore" - SOUTH_AFRICA = "South Africa" - SOUTH_KOREA = "South Korea" - SPAIN = "Spain" - SWEDEN = "Sweden" - SWITZERLAND = "Switzerland" - TAIWAN = "Taiwan" - TANZANIA = "Tanzania" - THAILAND = "Thailand" - TURKEY = "Turkey" - US_VIRGIN_ISLANDS = "U.S. Virgin Islands" - UNITED_ARAB_EMIRATES = "United Arab Emirates" - UNITED_KINGDOM = "United Kingdom" - UNITED_STATES = "United States" - URUGUAY = "Uruguay" - VIETNAM = "Vietnam" - - -class Region(Enum): - AFRICA = "Africa" - AMERICAS = "Americas" - ASIA = "Asia" - EUROPE = "Europe" - MIDDLE_EAST = "Middle East" - PACIFIC = "Pacific" - - -class SubMarket(Enum): - OTCQB = "OTCQB" - OTCQX = "OTCQX" - PINK = "PINK" - - -class Exchange(Enum): - OTC = "OTC" - NYSE_ARCA = "AMEX" - NASDAQ = "NASDAQ" - NYSE = "NYSE" - - -class Type(Enum): - STOCK = "stock" - DEPOSITORY_RECEIPT = "dr" - FUND = "fund" - STRUCTURED = "structured" - - -class SymbolType(Enum): - CLOSED_END_FUND = ["closedend"] - COMMON_STOCK = ["common"] - DEPOSITORY_RECEIPT = ["foreign-issuer"] - ETF = ["etf", "etf,odd", "etf,otc", "etf,cfd"] - ETN = ["etn"] - MUTUAL_FUND = ["mutual"] - PREFERRED_STOCK = ["preferred"] - REIT = ["reit", "reit,cfd", "trust,reit"] - STRUCTURED = [""] # ["SP"] - TRUST_FUND = ["trust"] - UIT = ["unit"] - - -class Rating(Enum): - STRONG_BUY = 0.5, 1, "Strong Buy" - BUY = 0.1, 0.5, "Buy" - NEUTRAL = -0.1, 0.1, "Neutral" - SELL = -0.5, -0.1, "Sell" - STRONG_SELL = -1, -0.5, "Strong Sell" - UNKNOWN = math.nan, math.nan, "Unknown" - - def __init__(self, min_, max_, label): - self.min = min_ - self.max = max_ - self.label = label - - def __contains__(self, item): - return self.min <= item <= self.max - - def range(self): - return [self.min, self.max] - - @classmethod - def find(cls, value: float): - if value is not None: - for rating in Rating: - if value in rating: - return rating - return Rating.UNKNOWN - - @classmethod - def names(cls): - return list(map(lambda c: c.name, cls)) - - @classmethod - def values(cls): - return list(map(lambda c: c.value, cls)) - - -class FilterOperator(Enum): - BELOW = "less" - BELOW_OR_EQUAL = "eless" - ABOVE = "greater" - ABOVE_OR_EQUAL = "egreater" - CROSSES = "crosses" - CROSSES_UP = "crosses_above" - CROSSES_DOWN = "crosses_below" - IN_RANGE = "in_range" - NOT_IN_RANGE = "not_in_range" - EQUAL = "equal" - NOT_EQUAL = "nequal" - MATCH = "match" - - -class ExtraFilter(Enum): - CURRENT_TRADING_DAY = "active_symbol" - SEARCH = "name,description" - PRIMARY = "is_primary" - - def __init__(self, value): - self.field_name = value - - -class Filter: - def __init__(self, field: Field | ExtraFilter, operation: FilterOperator, values): - self.field = field - self.operation = operation - self.values = values if isinstance(values, list) else [values] - -# def name(self): -# return self.field.field_name if isinstance(self.field, Field) else self.field.value - - def to_dict(self): - right = [filter_enum.value if isinstance(filter_enum, Enum) else filter_enum for filter_enum in self.values] - right = right[0] if len(right) == 1 else right - left = self.field.field_name - return {"left": left, "operation": self.operation.value, "right": right}