{"id":4997,"date":"2023-10-24T10:57:45","date_gmt":"2023-10-24T17:57:45","guid":{"rendered":"https:\/\/jeremywhittaker.com\/?p=4997"},"modified":"2023-11-01T18:07:56","modified_gmt":"2023-11-02T01:07:56","slug":"using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd","status":"publish","type":"post","link":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/","title":{"rendered":"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD"},"content":{"rendered":"\n<p>In a previous post, I showed how to <a href=\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/20\/python-for-finance-storing-stock-market-indices-and-symbols-with-eodhd\/\">store symbol data<\/a> from <a href=\"https:\/\/eodhd.com\/\">EODHD<\/a>. The purpose of this code is to now iterate through all those symbols and grab the Open, High, Low, Close, Adjustable Close, and Volume data from <a href=\"https:\/\/eodhd.com\/\">EODHD<\/a> using their API. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Output<\/h2>\n\n\n\n<p>This code will contain data for each stock symbol similar to this example for TSLA below for all 48,292 stocks.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image.png\"><img decoding=\"async\" width=\"1024\" height=\"580\" data-src=\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png\" alt=\"\" class=\"wp-image-4998 lazyload\" style=\"--smush-placeholder-width: 1024px; --smush-placeholder-aspect-ratio: 1024\/580;aspect-ratio:1.7655172413793103\" data-srcset=\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png 1024w, https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-300x170.png 300w, https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-768x435.png 768w, https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1536x870.png 1536w, https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-500x283.png 500w, https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image.png 1582w\" data-sizes=\"(max-width: 1024px) 100vw, 1024px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" \/><\/a><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>INFO:root:Processing 48930 symbols\nINFO:root:                Open      High       Low     Close  Adjusted_close     Volume\nDate                                                                         \n2010-06-29   18.9999   24.9999   17.5401   23.8899          1.5927  281749173\n2010-06-30   25.7901   30.4191   23.3001   23.8299          1.5887  257915884\n2010-07-01   24.9999   25.9200   20.2701   21.9600          1.4640  123447940\n2010-07-02   23.0001   23.1000   18.7101   19.2000          1.2800   77127102\n2010-07-06   20.0001   20.0001   15.8301   16.1100          1.0740  103189435\n...              ...       ...       ...       ...             ...        ...\n2023-10-17  250.1000  257.1830  247.0800  254.8500        254.8500   93562914\n2023-10-18  252.7000  254.6300  242.0800  242.6800        242.6800  125147797\n2023-10-19  225.9500  230.6100  216.7800  220.1100        220.1100  170772703\n2023-10-20  217.0100  218.8606  210.4200  211.9900        211.9900  138010094\n2023-10-23  210.0000  216.9800  202.5100  212.0800        212.0800  150215161\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Overview of the Script<\/h2>\n\n\n\n<p><br>The script performs the following tasks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Reads a list of stock symbols from an HDF5 file that we created previously which contains <a href=\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/20\/python-for-finance-storing-stock-market-indices-and-symbols-with-eodhd\/\">all the US stock symbols.<\/a><\/li>\n\n\n\n<li>Fetches the EOD stock price data for each symbol via an API call.<\/li>\n\n\n\n<li>Stores the fetched data in an HDF5 file.<\/li>\n\n\n\n<li>Keeps track of the last downloaded time for each symbol in a JSON log file.<\/li>\n\n\n\n<li>Allows for skipping previously downloaded data.<\/li>\n\n\n\n<li>Plots a simple candlestick chart of the data. <\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Deep Dive into the Code<\/h2>\n\n\n\n<p>Let&#8217;s dissect the code step by step, explaining each function&#8217;s purpose and the underlying logic.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Initial Setup<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Before diving into the functions, you&#8217;ve set up some important libraries and configurations:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Logging<\/strong>: Helps in tracking the flow and potential issues in the code.<\/li>\n\n\n\n<li><strong>Data Directory<\/strong>: A designated path where you store or read data.<\/li>\n\n\n\n<li><strong>API Key<\/strong>: Securely imported from a separate keys.py file to maintain security and modularity.<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\" start=\"2\">\n<li><strong>Function: get_symbols<\/strong><\/li>\n<\/ol>\n\n\n\n<p>This function is designed to fetch stock symbols from an existing HDF5 file.<\/p>\n\n\n\n<p>It first checks if the file exists. If not, it logs an informative message.<br>Then, it attempts to read the HDF5 file into a DataFrame.<br>The function ensures that the &#8216;Code&#8217; column exists before extracting the list of symbols.<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"3\">\n<li><strong>Function: fetch_eod_price_data<\/strong><\/li>\n<\/ol>\n\n\n\n<p>This is the core function of your script. Its main responsibilities include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fetching the EOD stock price data for each symbol.<\/li>\n\n\n\n<li>Skipping data that has recently been downloaded, using logs.<\/li>\n\n\n\n<li>Storing the fetched data in an HDF5 file.<\/li>\n\n\n\n<li>The function maintains a log of the last downloaded time for each symbol. This helps in efficiently updating your data without redundant API calls.<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\" start=\"4\">\n<li><strong>Main Execution<\/strong><\/li>\n<\/ol>\n\n\n\n<p>After defining the utility functions, the main execution of the script begins:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A list of stock symbols is fetched using the get_symbols function.<\/li>\n\n\n\n<li>The fetch_eod_price_data function is called to update the EOD price data.<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\" start=\"5\">\n<li><strong>Function: plot_candlestick_with_volume<\/strong><\/li>\n<\/ol>\n\n\n\n<p>This function is designed to visually represent the stock data:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It fetches the data for a particular stock from the HDF5 file.<\/li>\n\n\n\n<li>Filters the data based on the provided start and end dates.<\/li>\n\n\n\n<li>Plots a candlestick chart representing the stock&#8217;s price movements.<\/li>\n\n\n\n<li>On the same chart, it overlays a volume bar chart to indicate trading volumes on respective dates.<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\" start=\"6\">\n<li><strong>Visualization<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Finally, a candlestick chart with volume bars for the stock &#8216;TSLA&#8217; is plotted for a specific date range.<\/p>\n\n\n\n<p>Conclusion<\/p>\n\n\n\n<p>This script provides a streamlined approach to fetch, store, and visualize EOD stock price data. The modular design makes it easy to adapt and extend the functionalities as needed. Whether you&#8217;re a seasoned trader or just someone intrigued by stock market data, this script offers a solid foundation to build upon.<\/p>\n\n\n\n<p>In future posts, we&#8217;ll use Facebook&#8217;s Prophet to forward forecast this data into the future. <br><br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Code<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>import pandas as pd\nimport requests\nfrom io import StringIO\nfrom pathlib import Path\nimport logging\nimport json\nfrom datetime import datetime, timedelta\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\nfrom mplfinance.original_flavor import candlestick_ohlc\nimport matplotlib.dates as mdates\n\n\n\n\nlogging.basicConfig(level=logging.DEBUG)\n\ndata_dir = '\/home\/shared\/algos\/data\/'\nlog_file_path = \"symbol_price_data_time_log.json\"\n\nfrom keys import api_token\n\ndef get_symbols(h5_file_path, key='US'):\n    \"\"\"\n    Open an HDF5 file and return a list of symbols from the 'Code' column.\n\n    Parameters:\n        h5_file_path (str): The path to the HDF5 file.\n        key (str): The key to use when reading the HDF5 file. Default is 'exchanges'.\n\n    Returns:\n        list: A list of symbols if successful; otherwise, an empty list.\n    \"\"\"\n\n    h5_file_path = Path(h5_file_path)\n\n    # Check if the file exists\n    if not h5_file_path.exists():\n        logging.info(f\"The file {h5_file_path} does not exist.\")\n        return &#91;]\n\n    try:\n        # Read the DataFrame from the HDF5 file\n        df = pd.read_hdf(h5_file_path, key=key)\n\n        # Check if 'Code' column exists\n        if 'Code' not in df.columns:\n            logging.info(f\"The 'Code' column does not exist in the DataFrame.\")\n            return &#91;]\n\n        # Get the list of symbols from the 'Code' column\n        symbols = df&#91;'Code'].tolist()\n\n        return symbols\n\n    except Exception as e:\n        logging.error(f\"An error occurred: {e}\")\n        return &#91;]\n\n\ndef fetch_eod_price_data(stock_symbols, data_dir, log_file, skip_existing=True, hours_to_skip=24):\n    # Load existing logs if available\n    try:\n        with open(log_file, 'r') as f:\n            symbol_time_dict = json.load(f)\n    except FileNotFoundError:\n        symbol_time_dict = {}\n\n    all_data = {}\n    count = 0\n\n    # Create the directory if it doesn't exist\n    Path(data_dir).mkdir(parents=True, exist_ok=True)\n    hdf5_file_path = f\"{data_dir}\/eod_price_data.h5\"\n\n    existing_symbols = set()\n\n    if skip_existing:\n        with pd.HDFStore(hdf5_file_path, 'r') as store:\n            existing_symbols = {key&#91;1:] for key in store.keys()}\n\n\n    for symbol in tqdm(stock_symbols, desc='Fetching and storing EOD price data'):\n        last_downloaded_time = symbol_time_dict.get(symbol, None)\n\n        if skip_existing and symbol in existing_symbols:\n            continue\n\n        if last_downloaded_time:\n            last_downloaded_time = datetime.fromisoformat(last_downloaded_time)\n            time_since_last_download = datetime.now() - last_downloaded_time\n            if time_since_last_download &lt; timedelta(hours=hours_to_skip):\n                logging.info(f\"Data for symbol {symbol} was downloaded recently. Skipping...\")\n                continue\n\n        logging.info(f\"{symbol}: Downloading from EODHD...\")\n        url = f'https:\/\/eodhd.com\/api\/eod\/{symbol}.US?api_token={api_token}&amp;fmt=csv'\n        response = requests.get(url)\n        if response.status_code != 200:\n            logging.error(f\"Failed to fetch data for symbol {symbol}. HTTP Status Code: {response.status_code}\")\n            continue\n\n        csv_data = StringIO(response.text)\n        df = pd.read_csv(csv_data)\n\n\n        if 'Date' not in df.columns:\n            logging.error(f\"No 'Date' column in the data for symbol {symbol}. Skipping...\")\n            logging.error(f\"Data received: {response.text}\")\n            continue\n\n        # Set 'Date' as DateTime index\n        df&#91;'Date'] = pd.to_datetime(df&#91;'Date'])\n        df.set_index('Date', inplace=True)\n\n        # Add the DataFrame to the all_data dictionary\n        all_data&#91;symbol] = df\n\n        # Update log\n        symbol_time_dict&#91;symbol] = datetime.now().isoformat()\n        with open(log_file, 'w') as f:\n            json.dump(symbol_time_dict, f)\n\n        count += 1\n\n        # Update the HDF5 file every 100 symbols\n        if count % 100 == 0:\n            with pd.HDFStore(hdf5_file_path, mode='a') as store:\n                for symbol, data in all_data.items():\n                    store.put(symbol, data)\n            logging.info(f\"Saved {list(all_data.keys())} to HDF5 file.\")\n            all_data = {}\n\n    # Save remaining data to HDF5\n    if all_data:\n        with pd.HDFStore(hdf5_file_path, mode='a') as store:\n            for symbol, data in all_data.items():\n                store.put(symbol, data)\n        logging.info(f\"Saved remaining {list(all_data.keys())} to HDF5 file.\")\n\n    logging.info(\"Finished updating HDF5 file.\")\n\n\n\nsymbols = get_symbols(data_dir + 'symbols.h5', key='US')\nlogging.info(f'Processing {len(symbols)} symbols')\n\n\nfetch_eod_price_data(symbols, data_dir, log_file_path, skip_existing=True, hours_to_skip=72)\n\n\nsymbol = 'TSLA'\nhdf5_file_path = f\"{data_dir}\/eod_price_data.h5\"\n\n\ndef plot_candlestick_with_volume(symbol, hdf5_file_path, start_date, end_date):\n    with pd.HDFStore(hdf5_file_path, 'r') as store:\n        if f'\/{symbol}' in store.keys():\n            df = store.get(symbol)\n            logging.info(\"Data fetched successfully.\")\n\n            # Filter the DataFrame based on the start and end dates\n            df = df&#91;start_date:end_date]\n\n            # Ensure the DataFrame is sorted by date\n            df = df.sort_index()\n\n            # Convert date to a format that can be used by candlestick_ohlc\n            df&#91;'Date'] = df.index.map(mdates.date2num)\n\n            # Create subplots: one for candlestick, one for volume\n            fig, ax1 = plt.subplots(figsize=(10, 6))\n            ax2 = ax1.twinx()\n\n            # Plot candlestick chart\n            ohlc = df&#91;&#91;'Date', 'Open', 'High', 'Low', 'Adjusted_close']].copy()\n            candlestick_ohlc(ax1, ohlc.values, width=0.6, colorup='green', colordown='red')\n            ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))\n            ax1.set_xlabel('Date')\n            ax1.set_ylabel('Price')\n            ax1.set_title(f'Candlestick chart for {symbol} ({start_date} to {end_date})')\n            ax1.grid(True)\n\n            # Plot volume\n            ax2.bar(df.index, df&#91;'Volume'], color='gray', alpha=0.3)\n            ax2.set_ylabel('Volume')\n\n            plt.show()\n\n        else:\n            logging.info(f\"No data found for symbol: {symbol}\")\n\n\nsymbol = 'TSLA'\nhdf5_file_path = f\"{data_dir}\/eod_price_data.h5\"\nstart_date = '2023-01-01'\nend_date = '2023-10-23'\nplot_candlestick_with_volume(symbol, hdf5_file_path, start_date, end_date)<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>In a previous post, I showed how to store symbol data from EODHD. The purpose of this code is to now iterate through all those symbols and grab&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4997","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD - Jeremy Whittaker<\/title>\n<meta name=\"robots\" content=\"noindex, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD - Jeremy Whittaker\" \/>\n<meta property=\"og:description\" content=\"In a previous post, I showed how to store symbol data from EODHD. The purpose of this code is to now iterate through all those symbols and grab...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/\" \/>\n<meta property=\"og:site_name\" content=\"Jeremy Whittaker\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/WhittakerJeremy\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/WhittakerJeremy\" \/>\n<meta property=\"article:published_time\" content=\"2023-10-24T17:57:45+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-02T01:07:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png\" \/>\n<meta name=\"author\" content=\"JeremyWhittaker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"JeremyWhittaker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/\"},\"author\":{\"name\":\"JeremyWhittaker\",\"@id\":\"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c\"},\"headline\":\"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD\",\"datePublished\":\"2023-10-24T17:57:45+00:00\",\"dateModified\":\"2023-11-02T01:07:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/\"},\"wordCount\":555,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c\"},\"image\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/\",\"url\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/\",\"name\":\"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD - Jeremy Whittaker\",\"isPartOf\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png\",\"datePublished\":\"2023-10-24T17:57:45+00:00\",\"dateModified\":\"2023-11-02T01:07:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage\",\"url\":\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image.png\",\"contentUrl\":\"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image.png\",\"width\":1582,\"height\":896},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/new.jeremywhittaker.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/new.jeremywhittaker.com\/#website\",\"url\":\"https:\/\/new.jeremywhittaker.com\/\",\"name\":\"Jeremy Whittaker\",\"description\":\"Research, software, markets, housing, and energy\",\"publisher\":{\"@id\":\"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/new.jeremywhittaker.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c\",\"name\":\"JeremyWhittaker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g\",\"caption\":\"JeremyWhittaker\"},\"logo\":{\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g\"},\"sameAs\":[\"http:\/\/www.jeremywhittaker.com\",\"https:\/\/www.facebook.com\/WhittakerJeremy\",\"https:\/\/www.linkedin.com\/in\/jeremywhittaker\/\"],\"url\":\"https:\/\/new.jeremywhittaker.com\/index.php\/author\/jeremywhittaker\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD - Jeremy Whittaker","robots":{"index":"noindex","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"og_locale":"en_US","og_type":"article","og_title":"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD - Jeremy Whittaker","og_description":"In a previous post, I showed how to store symbol data from EODHD. The purpose of this code is to now iterate through all those symbols and grab...","og_url":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/","og_site_name":"Jeremy Whittaker","article_publisher":"https:\/\/www.facebook.com\/WhittakerJeremy","article_author":"https:\/\/www.facebook.com\/WhittakerJeremy","article_published_time":"2023-10-24T17:57:45+00:00","article_modified_time":"2023-11-02T01:07:56+00:00","og_image":[{"url":"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png","type":"","width":"","height":""}],"author":"JeremyWhittaker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"JeremyWhittaker","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#article","isPartOf":{"@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/"},"author":{"name":"JeremyWhittaker","@id":"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c"},"headline":"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD","datePublished":"2023-10-24T17:57:45+00:00","dateModified":"2023-11-02T01:07:56+00:00","mainEntityOfPage":{"@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/"},"wordCount":555,"commentCount":0,"publisher":{"@id":"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c"},"image":{"@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage"},"thumbnailUrl":"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/","url":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/","name":"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD - Jeremy Whittaker","isPartOf":{"@id":"https:\/\/new.jeremywhittaker.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage"},"image":{"@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage"},"thumbnailUrl":"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image-1024x580.png","datePublished":"2023-10-24T17:57:45+00:00","dateModified":"2023-11-02T01:07:56+00:00","breadcrumb":{"@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#primaryimage","url":"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image.png","contentUrl":"https:\/\/new.jeremywhittaker.com\/wp-content\/uploads\/2023\/10\/image.png","width":1582,"height":896},{"@type":"BreadcrumbList","@id":"https:\/\/new.jeremywhittaker.com\/index.php\/2023\/10\/24\/using-python-to-save-open-high-low-close-adjusted-close-and-volume-data-locally-from-eodhd\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/new.jeremywhittaker.com\/"},{"@type":"ListItem","position":2,"name":"How to Store Stock Market Data Locally with Python: A Step-by-Step Guide to Saving OHLCV Data from EODHD"}]},{"@type":"WebSite","@id":"https:\/\/new.jeremywhittaker.com\/#website","url":"https:\/\/new.jeremywhittaker.com\/","name":"Jeremy Whittaker","description":"Research, software, markets, housing, and energy","publisher":{"@id":"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/new.jeremywhittaker.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/new.jeremywhittaker.com\/#\/schema\/person\/ed0edfdefb3e180693efef453372980c","name":"JeremyWhittaker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g","caption":"JeremyWhittaker"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/c8ac20e6dfa86b5f27ce9bffee4851099770cbea5ae7338a274865bfbc8c0218?s=96&d=retro&r=g"},"sameAs":["http:\/\/www.jeremywhittaker.com","https:\/\/www.facebook.com\/WhittakerJeremy","https:\/\/www.linkedin.com\/in\/jeremywhittaker\/"],"url":"https:\/\/new.jeremywhittaker.com\/index.php\/author\/jeremywhittaker\/"}]}},"_links":{"self":[{"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/posts\/4997","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/comments?post=4997"}],"version-history":[{"count":7,"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/posts\/4997\/revisions"}],"predecessor-version":[{"id":5118,"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/posts\/4997\/revisions\/5118"}],"wp:attachment":[{"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/media?parent=4997"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/categories?post=4997"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/new.jeremywhittaker.com\/index.php\/wp-json\/wp\/v2\/tags?post=4997"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}