{"id":6151,"date":"2025-02-17T20:46:14","date_gmt":"2025-02-17T20:46:14","guid":{"rendered":"https:\/\/eodhd.com\/financial-academy\/?p=6151"},"modified":"2025-04-08T07:44:33","modified_gmt":"2025-04-08T07:44:33","slug":"beginner-stock-options-strategies","status":"publish","type":"post","link":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies","title":{"rendered":"Beginner Stock Options Strategies"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"439\" src=\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-1024x439.jpeg\" alt=\"\" class=\"wp-image-6335\" srcset=\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-1024x439.jpeg 1024w, https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-300x129.jpeg 300w, https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-768x329.jpeg 768w, https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-1536x658.jpeg 1536w, https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-2048x878.jpeg 2048w, https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-60x26.jpeg 60w, https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-150x64.jpeg 150w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Licensed Image from Adobe Stock<\/figcaption><\/figure>\n<\/div>\n\n\n<p>This article builds upon my previous piece, <em>&#8220;<a href=\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/us-stock-options-data-api-has-arrived\" target=\"_blank\" rel=\"noreferrer noopener\">US Stock Options Data API Has Arrived!<\/a>&#8220;<\/em> If you are unfamiliar with the concepts of stock options, it serves as a good starting point.<\/p>\n\n\n\n<p>In this article, I will evaluate three beginner strategies: <strong>Long Call<\/strong>, <strong>Long Put<\/strong>, and <strong>Covered Call<\/strong>. For each strategy, I will explain what it entails, how it works, the results of backtesting, and provide a visual representation.<\/p>\n\n\n\n<p class=\"has-luminous-vivid-orange-color has-text-color has-link-color wp-elements-a8d187ce71f8d739d7315560bd588791\">These are beginner strategies, so do not expect miracles. My aim is simply to provide an unbiased evaluation of each strategy, allowing you to determine whether it holds merit. This article is more to introduce the API and show you how to retrieve the data and pre-process it for analysis, and less about the specialist options metrics. That will be covered next in more advanced strategies. I also wanted to highlight that I&#8217;ve included a basic backtesting mechanism to compare the strategies. It does not factor in real word conditions like transactional fees and slippage which can have an amplified effect if a lot of buy and sell signals are triggered in quick succession.<\/p>\n\n\n\n<p style=\"font-size:16px\">Please note, API data availability depends on your subscription plan. Some data isn&#8217;t included in the free plan. Visit their <a href=\"https:\/\/eodhd.com\/pricing\" target=\"_blank\" rel=\"noreferrer noopener\">pricing page<\/a> to find the plan that fits your needs.<\/p>\n\n\n\n<p class=\"has-text-align-center\"><a class=\"maxbutton-1 maxbutton maxbutton-subscribe-to-api external-css btn\" href=\"https:\/\/eodhd.com\/register\"><span class='mb-text'>Register &amp; Get Data<\/span><\/a><\/p>\n\n\n\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-data-gathering\">Data Gathering<\/h2>\n\n\n\n<p>During my testing I did discover a &#8220;<em>gotcha<\/em>&#8221; with the Options API. In my previous article I explained that a &#8220;<em>limit<\/em>&#8221; and &#8220;<em>offset<\/em>&#8221; had been added which I liked. There is however a potential problem or at least limitation to be aware of. Options API restricts you to retrieving 100 days of data per call which is fine. So in theory to retrieve 100 days of Apple&#8217;s AAPL options data, it should in theory be this API call: <\/p>\n\n\n\n            <div class=\"code__wrapper\">\n                <div class=\"code__content\">\n                    \n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">https:\/\/eodhd.com\/api\/v2\/options\/AAPL.US?from=2024-09-11&amp;to=2024-12-20&amp;api_token=<strong>&lt;YOUR_API_KEY><\/strong><\/code><\/pre>\n\n                <\/div>\n                <div class=\"code__btns\">\n                    <button class=\"code__copy\" class=\"copy\" title=\"Copy url\">\n                        <svg class=\"code__copy__icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                            <use xlink:href=\"\/img\/icons\/copy.svg#copy\"><\/use>\n                        <\/svg>\n                        <img decoding=\"async\" class=\"code__copy__approve\" alt=\"\" src=\"\/img\/approve_ico.svg\" loading=\"eager\">\n                    <\/button>\n                <\/div>\n            <\/div>\n        \n\n\n<p><\/p>\n\n\n\n<p> The problem is omitting the &#8220;<em>offset<\/em>&#8221; and &#8220;<em>limit<\/em>&#8221; defaults to 0 and 1000. So in theory this should work right? <\/p>\n\n\n\n            <div class=\"code__wrapper\">\n                <div class=\"code__content\">\n                    \n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">https:\/\/eodhd.com\/api\/v2\/options\/AAPL.US?from=2024-09-11&amp;to=2024-12-20&amp;page[offset]=0&amp;page[limit]=100000&amp;api_token=https:\/\/eodhd.com\/api\/v2\/options\/AAPL.US?from=2024-09-11&amp;to=2024-12-20&amp;page[offset]=0&amp;page[limit]=10000&amp;api_token=<strong>&lt;YOUR_API_KEY><\/strong> <\/code><\/pre>\n\n                <\/div>\n                <div class=\"code__btns\">\n                    <button class=\"code__copy\" class=\"copy\" title=\"Copy url\">\n                        <svg class=\"code__copy__icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                            <use xlink:href=\"\/img\/icons\/copy.svg#copy\"><\/use>\n                        <\/svg>\n                        <img decoding=\"async\" class=\"code__copy__approve\" alt=\"\" src=\"\/img\/approve_ico.svg\" loading=\"eager\">\n                    <\/button>\n                <\/div>\n            <\/div>\n        \n\n\n<p>Wrong. There is a limitation that the API will only return 10000 entries. So if the 100 days exceeds 10000 data points it will fail. It should really be one restriction, not both.<\/p>\n\n\n\n<p>I still want to get a reasonable amount of options data to work with. I&#8217;ve come up with a plan and I will share it with you. I&#8217;m going to retrieve APPL options data between &#8220;2024-11-01&#8221; and &#8220;2025-02-07&#8221; in 1000 increments. I&#8217;ll then use the &#8220;next&#8221; key to iterate through the pages. I&#8217;ll then capture the key I&#8217;m really interested in which is &#8220;data&#8221; and create a dataset called &#8220;data\/options_data.csv&#8221;. My file has 141734 data points in it.<\/p>\n\n\n\n            <div class=\"code__wrapper\">\n                <div class=\"code__content\">\n                    \n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import os\nimport csv\nimport requests\nfrom dotenv import load_dotenv\n\nload_dotenv()\napi_token = os.getenv(\"EODHD_API_TOKEN\")\n\n\ndef fetch_options_data_to_csv(initial_url, csv_filename):\n    next_url = initial_url\n    fieldnames = None\n    first_page = True\n\n    while next_url:\n        next_url = f\"{next_url}&amp;api_token={api_token}\"\n\n        print(f\"Fetching data from: {next_url}\")\n        response = requests.get(next_url)\n        if response.status_code != 200:\n            print(f\"Failed to retrieve data (HTTP {response.status_code}). Exiting.\")\n            break\n\n        try:\n            json_response = response.json()\n        except ValueError:\n            print(\"Error decoding JSON response. Exiting.\")\n            break\n\n        records = json_response.get(\"data\", [])\n        if not records:\n            print(\"No records found on this page. Exiting loop.\")\n            break\n\n        if first_page:\n            fieldnames = list(records[0].keys())\n            mode = \"w\"\n            first_page = False\n        else:\n            mode = \"a\"\n\n        with open(csv_filename, mode, newline=\"\", encoding=\"utf-8\") as csvfile:\n            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)\n            if mode == \"w\":\n                writer.writeheader()\n            for record in records:\n                writer.writerow(record)\n\n        next_url = json_response.get(\"links\", {}).get(\"next\")\n\n    print(\"Data fetching completed.\")\n\n\nif __name__ == \"__main__\":\n    start_date = \"2024-11-01\"\n    end_date = \"2025-02-07\"\n    base_url = \"https:\/\/eodhd.com\/api\/v2\/options\/AAPL.US\"\n\n    initial_url = (\n        f\"{base_url}?from={start_date}&amp;to={end_date}\"\n        f\"&amp;page[offset]=0&amp;page[limit]=1000\"\n    )\n\n    csv_file = \"data\/options_data.csv\"\n\n    fetch_options_data_to_csv(initial_url, csv_file)<\/code><\/pre>\n\n                <\/div>\n                <div class=\"code__btns\">\n                    <button class=\"code__copy\" class=\"copy\" title=\"Copy url\">\n                        <svg class=\"code__copy__icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                            <use xlink:href=\"\/img\/icons\/copy.svg#copy\"><\/use>\n                        <\/svg>\n                        <img decoding=\"async\" class=\"code__copy__approve\" alt=\"\" src=\"\/img\/approve_ico.svg\" loading=\"eager\">\n                    <\/button>\n                <\/div>\n            <\/div>\n        \n\n\n<h2 class=\"wp-block-heading\" id=\"h-preprocessing\">Preprocessing<\/h2>\n\n\n\n<p>I now have my &#8220;data\/options_data.csv&#8221;. I loaded that into a Pandas dataframe to inspect it. There are a number of date fields and they aren&#8217;t sorted. I also noticed that the API doesn&#8217;t currently allow you to sort on all of them. I want to use &#8220;tradetime&#8221; for my time series. On closer inspection of this feature I also noticed that there were NaN entries. What I&#8217;ve done is removed the rows with the NaN entries, cast the column as a date field, and sorted the dataframe in ascending order.<\/p>\n\n\n\n            <div class=\"code__wrapper\">\n                <div class=\"code__content\">\n                    \n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import pandas as pd\n\n\ndef get_options_data():\n    return pd.read_csv(\"data\/options_data.csv\", low_memory=False)\n\n\nif __name__ == \"__main__\":\n    df = get_options_data()\n\n    df_cleaned = df.dropna(subset=[\"tradetime\"]).copy()\n    df_cleaned[\"tradetime\"] = pd.to_datetime(df_cleaned[\"tradetime\"], errors=\"coerce\")\n\n    df_sorted = df_cleaned.sort_values(by=\"tradetime\", ascending=True).copy()\n    df_sorted.reset_index(drop=True, inplace=True)\n\n    df[\"tradetime\"] = pd.to_datetime(df[\"tradetime\"])\n    df_sorted.index = df_sorted[\"tradetime\"]\n\n    df_sorted.to_csv(\"data\/options_data_preprocessed.csv\", index=True)<\/code><\/pre>\n\n                <\/div>\n                <div class=\"code__btns\">\n                    <button class=\"code__copy\" class=\"copy\" title=\"Copy url\">\n                        <svg class=\"code__copy__icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                            <use xlink:href=\"\/img\/icons\/copy.svg#copy\"><\/use>\n                        <\/svg>\n                        <img decoding=\"async\" class=\"code__copy__approve\" alt=\"\" src=\"\/img\/approve_ico.svg\" loading=\"eager\">\n                    <\/button>\n                <\/div>\n            <\/div>\n        \n\n\n<p>I think we&#8217;re in good shape now to apply our strategies. Our sorted pre-processed sorted data is in &#8220;<strong>data\/options_data_preprocessed.csv<\/strong>&#8221; now.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-long-call-strategy\">Long Call Strategy<\/h2>\n\n\n\n<p>A Long Call strategy involves buying call options with the expectation that the underlying stock price will rise. This strategy benefits from upward price movements, with the potential for unlimited profit and a loss limited to the premium paid.<\/p>\n\n\n\n<p><strong>Buy Signal<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Triggered when a significant upward trend is detected in the stock price, such as when the current price is above a moving average (e.g., 20-day SMA) and is increasing. Working off a 20-day SMA is simplistic for real-world trading, but this is a basic strategy.<\/li>\n<\/ul>\n\n\n\n<p><strong>Sell Signal<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Triggered if the stock price starts to decline below a threshold, such as crossing below a short-term moving average (e.g., 10-day SMA), or at a predefined profit target or expiration of the option. The sell signal I had to adjust to make the strategy profitable. The techniques I&#8217;ve used are more advanced but without this it&#8217;s highly unlikely this would be profitable. I implemented a stop loss, target profit, and trailing stop loss.<\/li>\n<\/ul>\n\n\n\n<p><strong>How Trigger Works in Code<\/strong>:<br>In the dataset:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A &#8220;Buy Call&#8221; signal is represented in the Signal column when the conditions for upward momentum are met. I will create the Signal column.<br><\/li>\n\n\n\n<li>The code assumes the Outcome column identifies whether the trade was profitable (&#8220;Win&#8221;) or not.<\/li>\n<\/ul>\n\n\n\n<p>Before I show you the code, I want to explain a few parts:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Loaded our sorted pre-processed CSV.<\/li>\n\n\n\n<li>Ensured the bid and ask columns are numeric.<\/li>\n\n\n\n<li>Replaced missing or erroneous entries with 0.<\/li>\n\n\n\n<li>Used interpolation and smoothing for bid values.<\/li>\n\n\n\n<li>Backtest the strategy with \u00a310,000.<\/li>\n\n\n\n<li>Return the buy\/sell transactions.<\/li>\n\n\n\n<li>Return a line graph with the buys and sells represented.<\/li>\n\n\n\n<li>Return the win\/loss ratio and ROI.<\/li>\n\n\n\n<li>Return the data gaps with missing or very low activity.<\/li>\n<\/ol>\n\n\n\n<p>When I coded this basic strategy and back tested it, it was terrible. The entire \u00a310,000 investment was wiped out. This strategy places thousands of buy and sell signals in quick succession. It does not allow for the order to gain enough momentum before selling (in most cases at a loss).<\/p>\n\n\n\n<p>I&#8217;ve carried out a lot of experiments like this and the key is a &#8220;smart sell&#8221;, not the buy. In most strategies the buy is usually pretty good but it&#8217;s the sell that sells to early before locking in each profit. What I&#8217;ve done is applied some of my experience to the basic strategy to make it hugely profitable. The trick is to make use of stop losses in both directions, and a trailing stop loss.<\/p>\n\n\n\n<p>This is a summary of what I&#8217;ve done to the strategy to turn it into something you can actually use.<\/p>\n\n\n\n<p><strong>Entry Conditions:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Signal:<\/strong> When no trade is open and the current bid is above the 20-period simple moving average (sma20).<\/li>\n\n\n\n<li><strong>Minimum Price Check:<\/strong> Trades are only entered if the bid price exceeds a set minimum (e.g. \u00a31) to avoid buying extremely low-priced assets.<\/li>\n\n\n\n<li><strong>Order Size:<\/strong> Only 1% of the current account balance is allocated per trade. I did experiment with higher values but 1% seemed to provide the best performance. Feel free to adjust the code below to try it out yourself.<\/li>\n\n\n\n<li><strong>Quantity Calculation:<\/strong> The number of units to buy is determined by dividing the allocated amount by the current bid, with a cap on maximum units to prevent oversized positions.<\/li>\n<\/ul>\n\n\n\n<p><strong>Exit Conditions:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Target Profit Exit:<\/strong> The trade is closed immediately if the bid price rises to 10% above the purchase price.<\/li>\n\n\n\n<li><strong>Hard Stop Loss:<\/strong> The trade is closed if the bid price drops to 3% below the purchase price.<\/li>\n\n\n\n<li><strong>Trailing Stop Loss:<\/strong>\n<ul class=\"wp-block-list\">\n<li>The strategy tracks the best price reached after entering the trade.<\/li>\n\n\n\n<li>If the current bid falls by more than 3% from this best price, the trade is exited.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Final Liquidation:<\/strong> Any open trade at the end of the data is closed at the last available price, determining a win or loss based on whether the exit price exceeds the purchase price.<\/li>\n<\/ul>\n\n\n\n<p><strong>Risk Management:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Smaller Position Size:<\/strong> Using only 1% of the balance per trade limits risk exposure on any single trade. <\/li>\n\n\n\n<li><strong>Multiple Stop Losses:<\/strong> Combining a hard stop loss with a trailing stop loss helps to cut losses quickly and protect profits.<\/li>\n<\/ul>\n\n\n\n<p>I also wanted to graph the data and put a green triangle on the graph when buys occur and a red triangle on the graph were sells occur. This didn&#8217;t work out the way I had hoped. There are just too many buy and sell signals and the graph looks like a mess. I did include the code for you to try out anyway. It&#8217;s useful code for visually inspecting strategies.<\/p>\n\n\n\n<p><strong>Visualisation:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Time Series Plot:<\/strong> The bid price is plotted over time.<\/li>\n\n\n\n<li><strong>Trade Markers:<\/strong> Green triangles mark buy orders and red triangles mark sell orders.<\/li>\n\n\n\n<li><strong>Downsampling:<\/strong> The dataset is downsampled (if necessary) to ensure efficient and responsive plotting.<\/li>\n<\/ul>\n\n\n\n            <div class=\"code__wrapper\">\n                <div class=\"code__content\">\n                    \n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-link-color wp-elements-91a7908de3c15ed44cc727bdbe433a75\"><code lang=\"python\" class=\"language-python\">import sys\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Read and preprocess data\ndf = pd.read_csv(\"data\/options_data_preprocessed.csv\", low_memory=False)\ndf[\"bid\"] = pd.to_numeric(df[\"bid\"], errors=\"coerce\")\ndf[\"ask\"] = pd.to_numeric(df[\"ask\"], errors=\"coerce\")\ndf[\"bid\"] = df[\"bid\"].replace(0, np.nan).astype(\"float64\")\ndf[\"bid\"] = df[\"bid\"].interpolate(method=\"linear\", limit_direction=\"both\")\ndf[\"bid\"] = df[\"bid\"].ffill().bfill()\n\n# Calculate moving averages\ndf[\"sma10\"] = df[\"bid\"].rolling(window=10).mean()\ndf[\"sma20\"] = df[\"bid\"].rolling(window=20).mean()\n\n# Convert tradetime to datetime objects\ndf[\"tradetime\"] = pd.to_datetime(df[\"tradetime\"])\n\ndef backtest_long_call_trailing(df, initial_investment,\n                                allocation_pct=0.01,\n                                target_profit_pct=0.10,\n                                stop_loss_pct=0.03,\n                                trailing_stop_pct=0.03,\n                                min_bid_threshold=1.0,\n                                max_quantity=1e6):\n\n    df[\"Signal\"] = None\n    open_trade = None  # Holds details of an open trade\n    balance = initial_investment\n    win_count = 0\n    loss_count = 0\n    trades = []\n    \n    for i in range(len(df)):\n        current_bid = df[\"bid\"].iloc[i]\n        current_ask = df[\"ask\"].iloc[i]\n        current_time = df[\"tradetime\"].iloc[i]\n        sma10 = df[\"sma10\"].iloc[i]\n        sma20 = df[\"sma20\"].iloc[i]\n        \n        # Skip if bid is missing or below threshold\n        if pd.isna(current_bid) or current_bid &lt; min_bid_threshold:\n            continue\n        \n        # Entry: if no trade is open and bid &gt; sma20, buy.\n        if open_trade is None and current_bid &gt; sma20:\n            allocation = balance * allocation_pct\n            quantity = allocation \/ current_bid\n            if quantity &gt; max_quantity:\n                quantity = max_quantity\n                allocation = quantity * current_bid\n            open_trade = {\n                \"purchase_price\": current_bid,\n                \"quantity\": quantity,\n                \"allocation\": allocation,\n                \"best_price\": current_bid\n            }\n            balance -= allocation\n            df.at[i, \"Signal\"] = \"Buy Call\"\n            trades.append((current_time, current_bid, \"Buy\", \"N\/A\"))\n        \n        # If trade is open, update best price and check exits.\n        elif open_trade is not None:\n            purchase_price = open_trade[\"purchase_price\"]\n            quantity = open_trade[\"quantity\"]\n            best_price = open_trade[\"best_price\"]\n            \n            # Update the best price achieved.\n            if current_bid &gt; best_price:\n                best_price = current_bid\n                open_trade[\"best_price\"] = best_price\n            \n            # Exit if target profit reached.\n            if current_bid &gt;= purchase_price * (1 + target_profit_pct):\n                proceeds = quantity * current_ask\n                balance += proceeds\n                win_count += 1\n                df.at[i, \"Signal\"] = \"Sell Call (Target)\"\n                trades.append((current_time, current_ask, \"Sell\", \"Win\"))\n                open_trade = None\n            \n            # Hard stop loss exit.\n            elif current_bid &lt;= purchase_price * (1 - stop_loss_pct):\n                proceeds = quantity * current_ask\n                balance += proceeds\n                loss_count += 1\n                df.at[i, \"Signal\"] = \"Sell Call (Stop Loss)\"\n                trades.append((current_time, current_ask, \"Sell\", \"Loss\"))\n                open_trade = None\n            \n            # Trailing stop loss exit.\n            elif current_bid &lt; best_price * (1 - trailing_stop_pct):\n                proceeds = quantity * current_ask\n                if current_ask &gt;= purchase_price:\n                    win_count += 1\n                    result = \"Win\"\n                else:\n                    loss_count += 1\n                    result = \"Loss\"\n                balance += proceeds\n                df.at[i, \"Signal\"] = \"Sell Call (Trailing Stop)\"\n                trades.append((current_time, current_ask, \"Sell\", result))\n                open_trade = None\n\n    # Final liquidation if a trade remains open.\n    if open_trade is not None:\n        last_bid = df[\"bid\"].iloc[-1]\n        last_ask = df[\"ask\"].iloc[-1]\n        proceeds = open_trade[\"quantity\"] * last_ask\n        if last_ask &gt;= open_trade[\"purchase_price\"]:\n            win_count += 1\n            result = \"Win\"\n        else:\n            loss_count += 1\n            result = \"Loss\"\n        trades.append((df[\"tradetime\"].iloc[-1], last_ask, \"Sell (End)\", result))\n        balance += proceeds\n        open_trade = None\n\n    return balance, win_count, loss_count, trades\n\n# Run the updated backtest.\ninitial_investment = 10000\nbalance_long_call, wins_long_call, losses_long_call, trades_long_call = backtest_long_call_trailing(df, initial_investment)\nwin_loss_ratio = wins_long_call \/ (losses_long_call if losses_long_call else 1)\nroi = ((balance_long_call - initial_investment) \/ initial_investment) * 100\n\nprint(\"Transaction Log:\")\nfor trade in trades_long_call:\n    date, price, action, result = trade\n    print(f\"Date: {date}, Action: {action}, Price: {price:.2f}, Result: {result}\")\n\nprint(f\"\\nFinal Balance: {balance_long_call:.2f}\")\nprint(f\"Wins: {wins_long_call}, Losses: {losses_long_call}\")\nprint(f\"Win\/Loss Ratio: {win_loss_ratio:.2f}\")\nprint(f\"ROI: {roi:.2f}%\")\n\n# --- Improved Plotting Section ---\n# Downsample the data to at most 1000 points for the main time series.\nn_points = 1000\nif len(df) &gt; n_points:\n    df_plot = df.iloc[::len(df)\/\/n_points].copy()\nelse:\n    df_plot = df.copy()\n\nplt.figure(figsize=(16, 8))\nplt.plot(df_plot[\"tradetime\"], df_plot[\"bid\"], label=\"Bid Price\", color=\"blue\")\n\n# Create lists for buy and sell markers.\nbuy_dates, buy_prices = [], []\nsell_dates, sell_prices = [], []\nfor trade in trades_long_call:\n    date, price, action, _ = trade\n    if action.startswith(\"Buy\"):\n        buy_dates.append(date)\n        buy_prices.append(price)\n    elif action.startswith(\"Sell\"):\n        sell_dates.append(date)\n        sell_prices.append(price)\n\nplt.scatter(buy_dates, buy_prices, marker=\"^\", color=\"green\", s=100, label=\"Buy\")\nplt.scatter(sell_dates, sell_prices, marker=\"v\", color=\"red\", s=100, label=\"Sell\")\n\nplt.title(\"Long Call Strategy Backtest with Trailing Stop Loss\")\nplt.xlabel(\"Tradetime\")\nplt.ylabel(\"Price\")\nplt.legend(loc=\"upper left\", bbox_to_anchor=(1, 1))\nplt.grid()\nplt.tight_layout()\nplt.show()<\/code><\/pre>\n\n                <\/div>\n                <div class=\"code__btns\">\n                    <button class=\"code__copy\" class=\"copy\" title=\"Copy url\">\n                        <svg class=\"code__copy__icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                            <use xlink:href=\"\/img\/icons\/copy.svg#copy\"><\/use>\n                        <\/svg>\n                        <img decoding=\"async\" class=\"code__copy__approve\" alt=\"\" src=\"\/img\/approve_ico.svg\" loading=\"eager\">\n                    <\/button>\n                <\/div>\n            <\/div>\n        \n\n\n<p>The results look like this:<\/p>\n\n\n\n<p>Final Balance: 62205.64<br>Wins: 10360, Losses: 14754<br>Win\/Loss Ratio: 0.70<br>ROI: 522.06%<\/p>\n\n\n\n<p>As you can see I my modifications helped \ud83d\ude42<\/p>\n\n\n\n<p>One thing you may wonder is why the final balance and ROI is so high yet there are so many losses compared with wins. The answer is the strategy now makes wins a lot more profitable, and the loss from losses is limited to the minimum. It&#8217;s also not factoring in transactional fees and slippage.<\/p>\n\n\n\n<p>Key issues to consider for optimising this basic strategy:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The SMA-20 strategy alone generates too many trades (over trading)<\/li>\n\n\n\n<li>There is no volatility or implied volatility consideration, this would reduce buying overpriced calls<\/li>\n\n\n\n<li>There is no consideration of time decay (theta)<\/li>\n\n\n\n<li>And most importantly it&#8217;s not factoring in real-world costs<\/li>\n\n\n\n<li>The stop loss and trailing stop loss triggers could be experimented with<\/li>\n<\/ol>\n\n\n\n<p>I&#8217;ve covered the first strategy now&#8230; let&#8217;s move into the next one!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-long-put-strategy\">Long Put Strategy<\/h2>\n\n\n\n<p>The next topic I want to cover is the differences between a Long Call (Long Buy) strategy and a Long Put strategy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Differences Between Long Call and Long Put Strategies<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Long Call (Long Buy) Strategy:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>Objective:<\/strong> Profit from an increase in the underlying asset\u2019s price.<\/li>\n\n\n\n<li><strong>Entry Condition:<\/strong> Enter the position when the underlying price is strong (e.g. above a moving average).<\/li>\n\n\n\n<li><strong>Profit:<\/strong> Increases as the underlying rises above the purchase price.<\/li>\n\n\n\n<li><strong>Risk:<\/strong> Limited to the premium paid; losses occur if the price does not rise.<\/li>\n\n\n\n<li><strong>Exit:<\/strong> Typically exit when a target profit is reached, a stop loss is hit, or when a trailing stop loss triggers after a price reversal.<br><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Long Put Strategy:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>Objective:<\/strong> Profit from a decrease in the underlying asset\u2019s price.<\/li>\n\n\n\n<li><strong>Entry Condition:<\/strong> Enter the position when the underlying price is weak (e.g. below a moving average).<\/li>\n\n\n\n<li><strong>Profit:<\/strong> Increases as the underlying falls further below the purchase price.<\/li>\n\n\n\n<li><strong>Risk:<\/strong> Also limited to the premium paid; losses occur if the price does not fall.<\/li>\n\n\n\n<li><strong>Exit:<\/strong> Exit when a target profit (i.e. a further drop) is reached, if a hard stop loss is hit (if the price moves upward too much), or via a trailing stop that locks in profits as the price falls and then reverses upward.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>I&#8217;ve made some changes to my Long Call code to test out this strategy.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Entry:<\/strong> The strategy enters a long put when no trade is open and the current bid is below the 20-period moving average (sma20).<\/li>\n\n\n\n<li><strong>Exit Conditions:<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>Target Profit:<\/strong> Exit when the bid falls further by a set percentage (e.g. 10% below the purchase price).<\/li>\n\n\n\n<li><strong>Hard Stop Loss:<\/strong> Exit if the bid rises above a set threshold (e.g. 3% above the purchase price).<\/li>\n\n\n\n<li><strong>Trailing Stop Loss:<\/strong> The strategy tracks the lowest price (i.e. the \u201cworst\u201d price for the underlying) since entry. If the bid then rises by more than 3% from that low, the trade is closed.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>I had a feeling this strategy would perform better on the dataset I have prepared based on how the previous strategy performed. The results were way too good. I&#8217;ve had to re-run the numbers several times as they seemed unrealistic to me. I&#8217;ve come to the conclusion the numbers may actually be correct. There are over 10,000 buy and sell opportunities. This would result in a very high ROI if real-world factors like slippage and transactional costs are not factored in. The basic backtesting code I&#8217;ve written doesn&#8217;t factor in fees and slippage.<\/p>\n\n\n\n<p>This is what the code looks like&#8230;<\/p>\n\n\n\n            <div class=\"code__wrapper\">\n                <div class=\"code__content\">\n                    \n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import sys\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\ndf = pd.read_csv(\"data\/options_data_preprocessed.csv\", low_memory=False)\ndf[\"bid\"] = pd.to_numeric(df[\"bid\"], errors=\"coerce\")\ndf[\"ask\"] = pd.to_numeric(df[\"ask\"], errors=\"coerce\")\ndf[\"bid\"] = df[\"bid\"].replace(0, np.nan).astype(\"float64\")\ndf[\"bid\"] = df[\"bid\"].interpolate(method=\"linear\", limit_direction=\"both\")\ndf[\"bid\"] = df[\"bid\"].ffill().bfill()\n\n# Calculate moving averages\ndf[\"sma10\"] = df[\"bid\"].rolling(window=10).mean()\ndf[\"sma20\"] = df[\"bid\"].rolling(window=20).mean()\n\n# Convert tradetime column to datetime objects\ndf[\"tradetime\"] = pd.to_datetime(df[\"tradetime\"])\n\n\ndef backtest_long_put_trailing_fixed(\n    df,\n    initial_investment,\n    allocation_pct=0.01,\n    target_profit_pct=0.10,\n    stop_loss_pct=0.03,\n    trailing_stop_pct=0.03,\n    min_bid_threshold=1.0,\n    max_quantity=1e6,\n):\n\n    # Use a fixed allocation for every trade.\n    fixed_allocation = initial_investment * allocation_pct\n\n    balance = initial_investment\n    win_count = 0\n    loss_count = 0\n    trades = []\n    open_trade = None  # This will hold details of the open trade, if any.\n\n    for i in range(len(df)):\n        current_bid = df[\"bid\"].iloc[i]\n        current_ask = df[\"ask\"].iloc[i]\n        current_time = df[\"tradetime\"].iloc[i]\n        sma20 = df[\"sma20\"].iloc[i]\n\n        # Skip if current_bid is missing or below our threshold.\n        if pd.isna(current_bid) or current_bid &lt; min_bid_threshold:\n            continue\n\n        # ENTRY: If no trade is open and current_bid is below sma20, enter a long put.\n        if open_trade is None and current_bid &lt; sma20:\n            allocation = fixed_allocation  # Fixed amount per trade.\n            quantity = allocation \/ current_bid\n            if quantity &gt; max_quantity:\n                quantity = max_quantity\n                allocation = quantity * current_bid\n            # Deduct the fixed allocation from the balance.\n            balance -= allocation\n            open_trade = {\n                \"purchase_price\": current_bid,\n                \"quantity\": quantity,\n                \"allocation\": allocation,\n                \"best_price\": current_bid,  # For a put, a higher price is better.\n            }\n            df.at[i, \"Signal\"] = \"Buy Put\"\n            trades.append((current_time, current_bid, \"Buy\", \"N\/A\"))\n\n        # If a trade is open, update the best (highest) price and check exit conditions.\n        elif open_trade is not None:\n            purchase_price = open_trade[\"purchase_price\"]\n            allocation = open_trade[\"allocation\"]\n            quantity = open_trade[\"quantity\"]\n            best_price = open_trade[\"best_price\"]\n\n            # Update best_price if current_bid is higher.\n            if current_bid &gt; best_price:\n                best_price = current_bid\n                open_trade[\"best_price\"] = best_price\n\n            # We'll use current_ask as the exit price.\n            exit_price = current_ask\n\n            # Calculate profit (or loss) for the trade:\n            # profit_loss = allocation * ((exit_price \/ purchase_price) - 1)\n            if current_bid &gt;= purchase_price * (1 + target_profit_pct):\n                profit_loss = allocation * ((exit_price \/ purchase_price) - 1)\n                balance += profit_loss  # Add only the profit (loss will be negative)\n                win_count += 1\n                df.at[i, \"Signal\"] = \"Sell Put (Target)\"\n                trades.append((current_time, exit_price, \"Sell\", \"Win\"))\n                open_trade = None\n\n            elif current_bid &lt;= purchase_price * (1 - stop_loss_pct):\n                profit_loss = allocation * ((exit_price \/ purchase_price) - 1)\n                balance += profit_loss\n                loss_count += 1\n                df.at[i, \"Signal\"] = \"Sell Put (Stop Loss)\"\n                trades.append((current_time, exit_price, \"Sell\", \"Loss\"))\n                open_trade = None\n\n            elif current_bid &lt; best_price * (1 - trailing_stop_pct):\n                profit_loss = allocation * ((exit_price \/ purchase_price) - 1)\n                # Determine win or loss based on exit price vs. purchase price.\n                if exit_price &gt;= purchase_price:\n                    win_count += 1\n                    result = \"Win\"\n                else:\n                    loss_count += 1\n                    result = \"Loss\"\n                balance += profit_loss\n                df.at[i, \"Signal\"] = \"Sell Put (Trailing Stop)\"\n                trades.append((current_time, exit_price, \"Sell\", result))\n                open_trade = None\n\n    # FINAL LIQUIDATION: If a trade remains open at the end of the data, exit it.\n    if open_trade is not None:\n        last_ask = df[\"ask\"].iloc[-1]\n        profit_loss = fixed_allocation * ((last_ask \/ open_trade[\"purchase_price\"]) - 1)\n        if last_ask &gt;= open_trade[\"purchase_price\"]:\n            win_count += 1\n            result = \"Win\"\n        else:\n            loss_count += 1\n            result = \"Loss\"\n        trades.append((df[\"tradetime\"].iloc[-1], last_ask, \"Sell (End)\", result))\n        balance += profit_loss\n        open_trade = None\n\n    return balance, win_count, loss_count, trades\n\n\ninitial_investment = 10000\nbalance_long_put, wins_long_put, losses_long_put, trades_long_put = (\n    backtest_long_put_trailing_fixed(\n        df,\n        initial_investment,\n        allocation_pct=0.01,\n        target_profit_pct=0.10,\n        stop_loss_pct=0.03,\n        trailing_stop_pct=0.03,\n        min_bid_threshold=1.0,\n        max_quantity=1e6,\n    )\n)\nwin_loss_ratio_put = wins_long_put \/ (losses_long_put if losses_long_put else 1)\nroi_put = ((balance_long_put - initial_investment) \/ initial_investment) * 100\n\nprint(\"Long Put Transaction Log:\")\nfor trade in trades_long_put:\n    date, price, action, result = trade\n    print(f\"Date: {date}, Action: {action}, Price: {price:.2f}, Result: {result}\")\n\nprint(f\"\\nFinal Balance: {balance_long_put:.2f}\")\nprint(f\"Wins: {wins_long_put}, Losses: {losses_long_put}\")\nprint(f\"Win\/Loss Ratio: {win_loss_ratio_put:.2f}\")\nprint(f\"ROI: {roi_put:.2f}%\")\n\nn_points = 1000\nif len(df) &gt; n_points:\n    df_plot = df.iloc[:: len(df) \/\/ n_points].copy()\nelse:\n    df_plot = df.copy()\n\nplt.figure(figsize=(16, 8))\nplt.plot(df_plot[\"tradetime\"], df_plot[\"bid\"], label=\"Bid Price\", color=\"blue\")\n\nbuy_dates, buy_prices = [], []\nsell_dates, sell_prices = [], []\nfor trade in trades_long_put:\n    date, price, action, _ = trade\n    if action.startswith(\"Buy\"):\n        buy_dates.append(date)\n        buy_prices.append(price)\n    elif action.startswith(\"Sell\"):\n        sell_dates.append(date)\n        sell_prices.append(price)\n\nplt.scatter(buy_dates, buy_prices, marker=\"^\", color=\"green\", s=100, label=\"Buy\")\nplt.scatter(sell_dates, sell_prices, marker=\"v\", color=\"red\", s=100, label=\"Sell\")\n\nplt.title(\"Long Put Strategy Backtest with Fixed Allocation\")\nplt.xlabel(\"Tradetime\")\nplt.ylabel(\"Price\")\nplt.legend(loc=\"upper left\", bbox_to_anchor=(1, 1))\nplt.grid()\nplt.tight_layout()\nplt.show()<\/code><\/pre>\n\n                <\/div>\n                <div class=\"code__btns\">\n                    <button class=\"code__copy\" class=\"copy\" title=\"Copy url\">\n                        <svg class=\"code__copy__icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                            <use xlink:href=\"\/img\/icons\/copy.svg#copy\"><\/use>\n                        <\/svg>\n                        <img decoding=\"async\" class=\"code__copy__approve\" alt=\"\" src=\"\/img\/approve_ico.svg\" loading=\"eager\">\n                    <\/button>\n                <\/div>\n            <\/div>\n        \n\n\n<p>And the results surprisingly look like this&#8230;<\/p>\n\n\n\n<p>Final Balance: 4587135.26<br>Wins: 12382, Losses: 11614<br>Win\/Loss Ratio: 1.07<br>ROI: 45771.35%<\/p>\n\n\n\n<p>You can see that this strategy performed better than the previous on in terms of the win\/loss ratio. The final balance and ROI still seems insanely high to me but I&#8217;ve checked it over severals times and I believe it&#8217;s likely correct and this high purely because fees and slippage is not factored in.<\/p>\n\n\n\n<p>This has very similar problems with the first strategy. Far too many buy signals in quick succession, no volatility-based entry conditions, and minimum trade hold periods to reduce overtrading. Options specific techniques like Greeks (Delta, Theta, Vega, and Gamma) may help here too. This moves more into advanced techniques but even these basic strategies could be improved further like I did with the sell signals.<\/p>\n\n\n\n<p>This bring bring us onto the last beginner strategy&#8230;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-covered-call\">Covered Call<\/h2>\n\n\n\n<p>Just for clarity let&#8217;s recap the previous two strategies and see what a Covered Call is.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Long Call<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>What it is:<\/strong> Buying a call option outright.<\/li>\n\n\n\n<li><strong>Goal:<\/strong> Profit from a rise in the underlying asset\u2019s price.<\/li>\n\n\n\n<li><strong>Risk\/Reward:<\/strong> Limited risk (the premium paid) and unlimited upside (in theory).<br><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Long Put<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>What it is:<\/strong> Buying a put option outright.<\/li>\n\n\n\n<li><strong>Goal:<\/strong> Profit from a fall in the underlying asset\u2019s price.<\/li>\n\n\n\n<li><strong>Risk\/Reward:<\/strong> Limited risk (the premium paid) and significant upside if the underlying falls dramatically.<br><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Covered Call<\/strong>\n<ul class=\"wp-block-list\">\n<li><strong>What it is:<\/strong> Owning shares of the underlying asset (a \u201clong stock\u201d position) while selling call options on that same asset.<\/li>\n\n\n\n<li><strong>Goal:<\/strong> Generate extra income (the call premium) on top of any capital gains in the stock. The premium cushions a drop in the stock price but limits upside because if the stock rises above the strike, the shares are called away.<\/li>\n\n\n\n<li><strong>Risk\/Reward:<\/strong> You hold the stock (with its inherent risks) but earn option premiums that enhance overall returns. If the stock rallies too high, your profit is capped at the strike price (plus premium).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p> I&#8217;ve been trying to get this strategy to return a positive result and no luck. I think maybe the market is too volatile. Through many iterations of trial and error I&#8217;ve managed to reduce the loss as much as I can. I&#8217;ve still not been able to get it to break even or show a positive result. <\/p>\n\n\n\n<p>I also changed the what is graphed as the previous two graphs above didn&#8217;t really show anything useful. I&#8217;ve changed it now to show the portfolio balance over time. I think this is better for all three strategies but you can decide for yourself.<\/p>\n\n\n\n<p>This is the code&#8230;<\/p>\n\n\n\n            <div class=\"code__wrapper\">\n                <div class=\"code__content\">\n                    \n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">import sys\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\ndf = pd.read_csv(\"data\/options_data_preprocessed.csv\", low_memory=False)\ndf[\"bid\"] = pd.to_numeric(df[\"bid\"], errors=\"coerce\")\ndf[\"ask\"] = pd.to_numeric(df[\"ask\"], errors=\"coerce\")\ndf[\"bid\"] = df[\"bid\"].replace(0, np.nan).astype(\"float64\")\ndf[\"bid\"] = df[\"bid\"].interpolate(method=\"linear\", limit_direction=\"both\")\ndf[\"bid\"] = df[\"bid\"].ffill().bfill()\n\n# Calculate a 20-period SMA for our signal.\ndf[\"sma20\"] = df[\"bid\"].rolling(window=20).mean()\n\n# Compute a 20-day rolling standard deviation and relative volatility.\ndf[\"vol_std\"] = df[\"bid\"].rolling(window=20).std()\ndf[\"rel_vol\"] = df[\"vol_std\"] \/ df[\"sma20\"]\n\n# Convert tradetime to datetime objects.\ndf[\"tradetime\"] = pd.to_datetime(df[\"tradetime\"])\n\n\ndef backtest_covered_call_partial_optimized(\n    df,\n    initial_investment,\n    trade_size=100,  # Fixed notional per trade (\u00a3100)\n    target_profit_pct=0.05,  # Call strike 5% above entry price.\n    stop_loss_pct=0.60,  # Stop loss if price falls 60% below entry.\n    option_duration=pd.Timedelta(\"30D\"),  # Option held for 30 days.\n    premium_pct=0.06,  # Premium equals 6% of trade value.\n    min_price_threshold=1.0,\n    min_trade_interval=pd.Timedelta(\"10D\"),  # Minimum 10 days between trades.\n    max_rel_volatility=0.10,  # Only enter trade if relative volatility &lt; 10%.\n):\n    balance = initial_investment\n    trade_log = []\n    portfolio_history = []\n    active_trade = None\n    last_trade_time = None\n\n    for i in range(len(df)):\n        current_time = df[\"tradetime\"].iloc[i]\n        current_price = df[\"bid\"].iloc[i]\n        sma20 = df[\"sma20\"].iloc[i]\n        rel_vol = df[\"rel_vol\"].iloc[i]\n\n        # Skip if current price is invalid.\n        if pd.isna(current_price) or current_price &lt; min_price_threshold:\n            continue\n\n        # Only enter trades if relative volatility is below our threshold.\n        if pd.isna(rel_vol) or rel_vol &gt; max_rel_volatility:\n            if active_trade is None:\n                portfolio_history.append((current_time, balance))\n            else:\n                mtm = active_trade[\"shares\"] * current_price\n                portfolio_history.append((current_time, balance + mtm))\n            continue\n\n        # Record portfolio value.\n        if active_trade is None:\n            portfolio_history.append((current_time, balance))\n        else:\n            mtm = active_trade[\"shares\"] * current_price\n            portfolio_history.append((current_time, balance + mtm))\n\n        # Enforce minimum trade interval.\n        if (\n            last_trade_time is not None\n            and (current_time - last_trade_time) &lt; min_trade_interval\n        ):\n            if active_trade is None:\n                continue\n\n        # If an active trade exists, check exit conditions.\n        if active_trade is not None:\n            entry_price = active_trade[\"entry_price\"]\n            shares = active_trade[\"shares\"]\n            expiry = active_trade[\"expiry\"]\n            strike = active_trade[\"strike\"]\n            premium = active_trade[\"premium\"]\n\n            # Stop Loss: Exit if current price falls to or below entry_price * (1 - stop_loss_pct).\n            if current_price &lt;= entry_price * (1 - stop_loss_pct):\n                proceeds = shares * current_price\n                profit = proceeds - trade_size\n                trade_log.append(\n                    (current_time, current_price, \"Stop Loss\", f\"Profit: {profit:.2f}\")\n                )\n                balance += profit\n                active_trade = None\n                last_trade_time = current_time\n                continue\n\n            # Option Expiry: If current_time &gt;= expiry, settle the trade.\n            if current_time &gt;= expiry:\n                if current_price &gt;= strike:\n                    proceeds = shares * strike + premium\n                    action_str = \"Call Exercised\"\n                else:\n                    proceeds = shares * current_price + premium\n                    action_str = \"Call Expired\"\n                profit = proceeds - trade_size\n                trade_log.append(\n                    (current_time, current_price, action_str, f\"Profit: {profit:.2f}\")\n                )\n                balance += profit\n                active_trade = None\n                last_trade_time = current_time\n                continue\n\n            continue\n\n        # If no active trade, check for an entry signal.\n        if active_trade is None and current_price &gt; sma20:\n            allocation = trade_size\n            shares = allocation \/ current_price\n            entry_price = current_price\n            strike = current_price * (1 + target_profit_pct)\n            premium = shares * current_price * premium_pct\n            expiry = current_time + option_duration\n            active_trade = {\n                \"entry_time\": current_time,\n                \"entry_price\": entry_price,\n                \"shares\": shares,\n                \"allocation\": allocation,\n                \"strike\": strike,\n                \"premium\": premium,\n                \"expiry\": expiry,\n            }\n            balance -= allocation\n            trade_log.append(\n                (\n                    current_time,\n                    current_price,\n                    \"Enter Trade\",\n                    f\"Trade Size: {allocation:.2f}, Strike: {strike:.2f}, Premium: {premium:.2f}, Expiry: {expiry}\",\n                )\n            )\n            last_trade_time = current_time\n\n    # Final liquidation if a trade is still active.\n    if active_trade is not None:\n        final_price = df[\"bid\"].iloc[-1]\n        proceeds = active_trade[\"shares\"] * final_price\n        profit = proceeds - trade_size\n        trade_log.append(\n            (\n                df[\"tradetime\"].iloc[-1],\n                final_price,\n                \"Liquidate End\",\n                f\"Profit: {profit:.2f}\",\n            )\n        )\n        balance += profit\n        active_trade = None\n        portfolio_history.append((df[\"tradetime\"].iloc[-1], balance))\n\n    return balance, portfolio_history, trade_log\n\n\ninitial_investment = 10000\nfinal_balance, portfolio_history, trade_log = backtest_covered_call_partial_optimized(\n    df,\n    initial_investment,\n    trade_size=100,  # Fixed \u00a3100 per trade.\n    target_profit_pct=0.05,  # 5% target profit.\n    stop_loss_pct=0.60,  # 60% stop loss.\n    option_duration=pd.Timedelta(\"30D\"),  # Hold option for 30 days.\n    premium_pct=0.06,  # 6% premium.\n    min_price_threshold=1.0,\n    min_trade_interval=pd.Timedelta(\"10D\"),  # Minimum 10 days between trades.\n    max_rel_volatility=0.10,  # Only trade if 20-day relative volatility &lt; 10%.\n)\nroi = ((final_balance - initial_investment) \/ initial_investment) * 100\n\nprint(\"Final Optimized Partial Covered Call Trade Log:\")\nfor rec in trade_log:\n    time, price, action, details = rec\n    print(f\"Date: {time}, Price: {price:.2f}, Action: {action}, Details: {details}\")\n\nprint(f\"\\nFinal Portfolio Balance: {final_balance:.2f}\")\nprint(f\"ROI: {roi:.2f}%\")\n\ntimes, values = zip(*portfolio_history)\nplt.figure(figsize=(16, 8))\nplt.plot(times, values, label=\"Portfolio Value\", color=\"blue\")\nplt.title(\"Final Optimized Partial Covered Call Portfolio Value Over Time\")\nplt.xlabel(\"Tradetime\")\nplt.ylabel(\"Portfolio Value (\u00a3)\")\nplt.legend(loc=\"upper left\")\nplt.grid()\nplt.tight_layout()\nplt.show()<\/code><\/pre>\n\n                <\/div>\n                <div class=\"code__btns\">\n                    <button class=\"code__copy\" class=\"copy\" title=\"Copy url\">\n                        <svg class=\"code__copy__icon\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                            <use xlink:href=\"\/img\/icons\/copy.svg#copy\"><\/use>\n                        <\/svg>\n                        <img decoding=\"async\" class=\"code__copy__approve\" alt=\"\" src=\"\/img\/approve_ico.svg\" loading=\"eager\">\n                    <\/button>\n                <\/div>\n            <\/div>\n        \n\n\n<p>And the result looks like this&#8230;<\/p>\n\n\n\n<p>Final Portfolio Balance: 8702.58<br>ROI: -12.97%<br><br>It&#8217;s a loss but all strategies being profitable just isn&#8217;t realistic. At least we have a comparison between all three.<\/p>\n\n\n\n<p>Although this strategy at first glance performed the worst, it is probably the most well-established income-generating strategy. The poor performance could be due to the stock selection mostly due to high market volatility, and option strikes and premiums not being optimised. There are more advanced techniques like rolling of options that may help here.<br><br>I hope you liked the article and found it interesting. The next article will look at more advanced strategies like <strong>Straddle<\/strong>, <strong>Strangle<\/strong>, <strong>Vertical Spreads<\/strong>, and <strong>Iron Condor<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article builds upon my previous piece, &#8220;US Stock Options Data API Has Arrived!&#8220; If you are unfamiliar with the concepts of stock options, it serves as a good starting point. In this article, I will evaluate three beginner strategies: Long Call, Long Put, and Covered Call. For each strategy, I will explain what it [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":6335,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[93,59],"tags":[94],"coding-language":[30],"ready-to-go-solution":[],"qualification":[31],"financial-apis-category":[],"financial-apis-manuals":[40],"class_list":["post-6151","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stock-options","category-technical-analysis-examples","tag-options","coding-language-python","qualification-experienced","financial-apis-manuals-technical-indicators","has_thumb"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.9 (Yoast SEO v26.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Beginner Stock Options Strategies | EODHD APIs Academy<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Beginner Stock Options Strategies\" \/>\n<meta property=\"og:description\" content=\"This article builds upon my previous piece, &#8220;US Stock Options Data API Has Arrived!&#8220; If you are unfamiliar with the concepts of stock options, it serves as a good starting point. In this article, I will evaluate three beginner strategies: Long Call, Long Put, and Covered Call. For each strategy, I will explain what it [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies\" \/>\n<meta property=\"og:site_name\" content=\"Financial Academy\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/eodhistoricaldata\" \/>\n<meta property=\"article:published_time\" content=\"2025-02-17T20:46:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-08T07:44:33+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1097\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Michael Whittle\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@EOD_data\" \/>\n<meta name=\"twitter:site\" content=\"@EOD_data\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michael Whittle\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#article\",\"isPartOf\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies\"},\"author\":{\"name\":\"Michael Whittle\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/50784c270b6267df5969514d80d510ad\"},\"headline\":\"Beginner Stock Options Strategies\",\"datePublished\":\"2025-02-17T20:46:14+00:00\",\"dateModified\":\"2025-04-08T07:44:33+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies\"},\"wordCount\":2502,\"publisher\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#organization\"},\"image\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage\"},\"thumbnailUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg\",\"keywords\":[\"options\"],\"articleSection\":[\"Stock Options\",\"Technical Analysis Examples\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies\",\"name\":\"Beginner Stock Options Strategies | EODHD APIs Academy\",\"isPartOf\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage\"},\"image\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage\"},\"thumbnailUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg\",\"datePublished\":\"2025-02-17T20:46:14+00:00\",\"dateModified\":\"2025-04-08T07:44:33+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg\",\"contentUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg\",\"width\":2560,\"height\":1097},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/eodhd.com\/financial-academy\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Beginner Stock Options Strategies\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#website\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/\",\"name\":\"Financial APIs Academy | EODHD\",\"description\":\"Financial Stock Market Academy\",\"publisher\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/eodhd.com\/financial-academy\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#organization\",\"name\":\"EODHD (EOD Historical Data)\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png\",\"contentUrl\":\"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png\",\"width\":159,\"height\":82,\"caption\":\"EODHD (EOD Historical Data)\"},\"image\":{\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/eodhistoricaldata\",\"https:\/\/x.com\/EOD_data\",\"https:\/\/www.reddit.com\/r\/EODHistoricalData\/\",\"https:\/\/eod-historical-data.medium.com\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/50784c270b6267df5969514d80d510ad\",\"name\":\"Michael Whittle\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5076af85c7ee0445454257247cad4970ae8cf5d7d4940d2b32c521f51c0a0f5a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5076af85c7ee0445454257247cad4970ae8cf5d7d4940d2b32c521f51c0a0f5a?s=96&d=mm&r=g\",\"caption\":\"Michael Whittle\"},\"description\":\"Solution architect, developer, and analyst with over 20+ years experience (TOP author on Medium).\",\"url\":\"https:\/\/eodhd.com\/financial-academy\/author\/michaelwhittle\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Beginner Stock Options Strategies | EODHD APIs Academy","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies","og_locale":"en_US","og_type":"article","og_title":"Beginner Stock Options Strategies","og_description":"This article builds upon my previous piece, &#8220;US Stock Options Data API Has Arrived!&#8220; If you are unfamiliar with the concepts of stock options, it serves as a good starting point. In this article, I will evaluate three beginner strategies: Long Call, Long Put, and Covered Call. For each strategy, I will explain what it [&hellip;]","og_url":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies","og_site_name":"Financial Academy","article_publisher":"https:\/\/www.facebook.com\/eodhistoricaldata","article_published_time":"2025-02-17T20:46:14+00:00","article_modified_time":"2025-04-08T07:44:33+00:00","og_image":[{"width":2560,"height":1097,"url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg","type":"image\/jpeg"}],"author":"Michael Whittle","twitter_card":"summary_large_image","twitter_creator":"@EOD_data","twitter_site":"@EOD_data","twitter_misc":{"Written by":"Michael Whittle","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#article","isPartOf":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies"},"author":{"name":"Michael Whittle","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/50784c270b6267df5969514d80d510ad"},"headline":"Beginner Stock Options Strategies","datePublished":"2025-02-17T20:46:14+00:00","dateModified":"2025-04-08T07:44:33+00:00","mainEntityOfPage":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies"},"wordCount":2502,"publisher":{"@id":"https:\/\/eodhd.com\/financial-academy\/#organization"},"image":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage"},"thumbnailUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg","keywords":["options"],"articleSection":["Stock Options","Technical Analysis Examples"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies","url":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies","name":"Beginner Stock Options Strategies | EODHD APIs Academy","isPartOf":{"@id":"https:\/\/eodhd.com\/financial-academy\/#website"},"primaryImageOfPage":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage"},"image":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage"},"thumbnailUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg","datePublished":"2025-02-17T20:46:14+00:00","dateModified":"2025-04-08T07:44:33+00:00","breadcrumb":{"@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#primaryimage","url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg","contentUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg","width":2560,"height":1097},{"@type":"BreadcrumbList","@id":"https:\/\/eodhd.com\/financial-academy\/technical-analysis-examples\/beginner-stock-options-strategies#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/eodhd.com\/financial-academy\/"},{"@type":"ListItem","position":2,"name":"Beginner Stock Options Strategies"}]},{"@type":"WebSite","@id":"https:\/\/eodhd.com\/financial-academy\/#website","url":"https:\/\/eodhd.com\/financial-academy\/","name":"Financial APIs Academy | EODHD","description":"Financial Stock Market Academy","publisher":{"@id":"https:\/\/eodhd.com\/financial-academy\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/eodhd.com\/financial-academy\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/eodhd.com\/financial-academy\/#organization","name":"EODHD (EOD Historical Data)","url":"https:\/\/eodhd.com\/financial-academy\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/","url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png","contentUrl":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2023\/12\/EODHD-Logo.png","width":159,"height":82,"caption":"EODHD (EOD Historical Data)"},"image":{"@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/eodhistoricaldata","https:\/\/x.com\/EOD_data","https:\/\/www.reddit.com\/r\/EODHistoricalData\/","https:\/\/eod-historical-data.medium.com\/"]},{"@type":"Person","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/50784c270b6267df5969514d80d510ad","name":"Michael Whittle","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/eodhd.com\/financial-academy\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5076af85c7ee0445454257247cad4970ae8cf5d7d4940d2b32c521f51c0a0f5a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5076af85c7ee0445454257247cad4970ae8cf5d7d4940d2b32c521f51c0a0f5a?s=96&d=mm&r=g","caption":"Michael Whittle"},"description":"Solution architect, developer, and analyst with over 20+ years experience (TOP author on Medium).","url":"https:\/\/eodhd.com\/financial-academy\/author\/michaelwhittle"}]}},"jetpack_featured_media_url":"https:\/\/eodhd.com\/financial-academy\/wp-content\/uploads\/2025\/02\/AdobeStock_316533603-scaled.jpeg","jetpack_shortlink":"https:\/\/wp.me\/pdOdVT-1Bd","jetpack_sharing_enabled":true,"acf":[],"_links":{"self":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts\/6151","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/comments?post=6151"}],"version-history":[{"count":8,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts\/6151\/revisions"}],"predecessor-version":[{"id":6346,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/posts\/6151\/revisions\/6346"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/media\/6335"}],"wp:attachment":[{"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/media?parent=6151"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/categories?post=6151"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/tags?post=6151"},{"taxonomy":"coding-language","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/coding-language?post=6151"},{"taxonomy":"ready-to-go-solution","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/ready-to-go-solution?post=6151"},{"taxonomy":"qualification","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/qualification?post=6151"},{"taxonomy":"financial-apis-category","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/financial-apis-category?post=6151"},{"taxonomy":"financial-apis-manuals","embeddable":true,"href":"https:\/\/eodhd.com\/financial-academy\/wp-json\/wp\/v2\/financial-apis-manuals?post=6151"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}