{"id":18983,"date":"2023-10-03T14:00:00","date_gmt":"2023-10-03T06:00:00","guid":{"rendered":"https:\/\/www.tejwin.com\/?post_type=insight&#038;p=18983"},"modified":"2023-10-25T13:13:15","modified_gmt":"2023-10-25T05:13:15","slug":"when-tej-api-database-meets-up-streamlit-grid-trading-app","status":"publish","type":"insight","link":"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/","title":{"rendered":"When TEJ API Database Meets Up STREAMLIT Grid Trading\u00a0App"},"content":{"rendered":"\n<figure class=\"wp-block-image aligncenter caption-align-center\"><img decoding=\"async\" src=\"https:\/\/www.tejwin.com\/wp-content\/uploads\/0gHDaII8XZSFOiddX.jpg\" alt=\"\u3010\u65b0\u624b\u5165\u9580\u3011\u7576 TEJ API \u8cc7\u6599\u5eab\u9047\u4e0aSTREAMLIT\u7db2\u683c\u4ea4\u6613 App\"\/><figcaption class=\"wp-element-caption\">Photo by <a href=\"https:\/\/unsplash.com\/@austindistel?utm_source=medium&amp;utm_medium=referral\" target=\"_blank\" rel=\"noreferrer noopener\">Austin Distel<\/a> on&nbsp;<a href=\"https:\/\/unsplash.com?utm_source=medium&amp;utm_medium=referral\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\">Unsplash<\/a><\/figcaption><\/figure>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_81 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-69f7d4121db10\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"ez-toc-cssicon\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-69f7d4121db10\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Keywords\" >Keywords<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Highlight\" >Highlight<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Preface\" >Preface<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#The_Interface_of_the_Trading_App\" >The Interface of the Trading\u00a0App<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Programming_environment_and_Module_required\" >Programming environment and Module\u00a0required<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Database_Usage\" >Database Usage<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#1_Setting_Tools_for_Stock_Start_Date_and_End_Date\" >1. Setting Tools for Stock Start Date and End Date<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#2_Dropdown_Menu_for_Stock_Codes\" >2. Dropdown Menu for Stock\u00a0Codes<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#3_Setting_Upper_Bound_Lower_Bound_and_Grid_Interval_Tools\" >3. Setting Upper Bound, Lower Bound, and Grid Interval\u00a0Tools<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Setting_up_Right-side_Charts_Datasets_and_Returns\" >Setting up Right-side Charts, Datasets, and\u00a0Returns<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#1_Data_Processing\" >1. Data Processing<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#2_Trading_Signal_Charts\" >2. Trading Signal\u00a0Charts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#3_Creating_Datasets\" >3. Creating\u00a0Datasets<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#4_Setting_Up_Trading_Data_Table_and_Investment_Performance_Table\" >4. Setting Up Trading Data Table and Investment Performance Table<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Opening_STREAMLIT\" >Opening STREAMLIT<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Conclusion\" >Conclusion<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Source_Code\" >Source Code<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Extended_Reading\" >Extended Reading<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-database-meets-up-streamlit-grid-trading-app\/#Related_Links\" >Related Links<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Keywords\"><\/span>Keywords<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>STREAMLIT\u3001Data Visualization\u3001Grid Trading<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Highlight\"><\/span>Highlight<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Article Difficulty: \u2605\u2605\u2605\u2606\u2606<\/li>\n\n\n\n<li>STREAMLIT APP for Data Visualization<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Preface\"><\/span><strong>Preface<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In previous tutorials, we learned how to create our own STREAMLIT App. For more details, you can refer to <a aria-label=\" (opens in a new tab)\" href=\"https:\/\/www.tejwin.com\/en\/insight\/when-tej-api-meets-streamlit-app\/\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\">this article<\/a>. In this article, we will use the TEJ API database to connect with the STREAMLIT package and implement a grid trading strategy. We will use tools such as date selection, dropdown menus, and numerical selectors to interact with charts and tables, making the data an interactive app.<\/p>\n\n\n\n<p>Grid trading is a trading strategy that selects a range by setting two parameters, the upper bound and the lower bound. We divide the stock price into grid intervals, buying stocks when the price falls and touches the lower grid, and selling stocks when the price rises and exceeds the upper grid.<\/p>\n\n\n\n<p>This strategy is a lazy strategy that doesn\u2019t require much manual operation. It can also profit from price fluctuations. However, there are a few points to note which is the efficiency of capital utilization will be lower than manual trading.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Interface_of_the_Trading_App\"><\/span>The Interface of the Trading\u00a0App<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/www.tejwin.com\/wp-content\/uploads\/18eLJQF8G-d0MqhcQ4-MT5A.gif\" alt=\"\u672c\u6b21\u5be6\u4f5c\u7684\u4ea4\u6613APP\u756b\u9762\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Programming_environment_and_Module_required\"><\/span>Programming environment and Module\u00a0required<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>We use Windows and VScode as the editor in this article.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code># STREAMLIT\u5957\u4ef6\nimport streamlit as st\nimport pandas as pd\n# \u53ef\u4ee5\u4e92\u52d5\u7684PLOT\u5957\u4ef6\nimport plotly.graph_objects as go\n# \u8a2d\u7f6e\u65e5\u671f\u683c\u5f0f\u7684\u5957\u4ef6\nimport datetime\nfrom datetime import datetime as dt\nfrom datetime import timedelta \nimport tejapi\n\n# \u767b\u5165TEJ API\ntejapi.ApiConfig.api_key = your_key\n#\u628a\u6642\u9593\u53d6\u6d88\u4fdd\u7559\u65e5\u671f (\u7121\u8996)\ntejapi.ApiConfig.ignoretz = True<\/code><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Database_Usage\"><\/span>Database Usage<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>. <a href=\"https:\/\/api.tej.com.tw\/columns.html?idCode=TWN%2FAPIPRCD\" rel=\"noreferrer noopener\" target=\"_blank\"><strong>\u4ea4\u6613\u8cc7\u6599-\u80a1\u50f9\u8cc7\u6599<\/strong>(TMN\/APIPRCD)<\/a><\/p>\n\n\n\n<p><strong><strong>Sidebar Widget Settings<\/strong><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter caption-align-center\"><img decoding=\"async\" src=\"https:\/\/www.tejwin.com\/wp-content\/uploads\/1OMOpcHMPpKTtTAQG50AlFg.png\" alt=\"\u5de6\u5074\u5de5\u5177\u6b04\u4f4d\"\/><figcaption class=\"wp-element-caption\">\u5de6\u5074\u5de5\u5177\u6b04\u4f4d<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"1_Setting_Tools_for_Stock_Start_Date_and_End_Date\"><\/span>1. Setting Tools for Stock Start Date and End Date<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><code>col1, col2 = st.columns(2)\nwith col1:\n        # \u5c07\u80a1\u7968\u8d77\u4f7f\u65e5\u671f\u8a2d\u7f6e\u70ba\u8b8a\u6578d1\n        d1 = st.date_input(\n        \"\u80a1\u7968\u8d77\u59cb\u65e5\u671f\",\n        # \u4e26\u5c07\u9810\u8a2d\u8cc7\u6599\u8a2d\u5b9a\u70ba2022\u5e74\u76841\/1\n        datetime.date(2022, 1, 1))\n\n    with col2:\n        # \u5c07\u80a1\u7968\u8d77\u4f7f\u65e5\u671f\u8a2d\u7f6e\u70ba\u8b8a\u6578d2\n        d2= st.date_input(\n        \"\u80a1\u7968\u7d50\u675f\u65e5\u671f\",\n        datetime.date(2023, 2, 3))<\/code><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"2_Dropdown_Menu_for_Stock_Codes\"><\/span>2. Dropdown Menu for Stock\u00a0Codes<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Since the stock data for the current day has not closed, fetching data for the current day would result in an error. Therefore, we fetch data for yesterday and only keep the \u201ccoid\u201d (stock name) column in the \u201copts\u201d variable.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>#\u8f38\u5165\u80a1\u50f9\n# \u4f7f\u7528date\u5957\u4ef6\u7684date\u7372\u53d6\u4eca\u5929\u7684\u65e5\u671f\u8cc7\u6599\ncurrent_date = dt.now().date()\n    # \u4f7f\u7528date\u5957\u4ef6\u7684timedelta\u7372\u53d6\u6628\u5929\u7684\u65e5\u671f\u8cc7\u6599\n    previous_date = current_date - timedelta(days=1)\n    data = tejapi.get('TWN\/APIPRCD',\n                  mdate=previous_date,\n                  opts={'columns':&#91;'coid']},\n                  paginate=True)\n    \n    coids = data&#91;'coid'].tolist()\n    stock_code = st.selectbox('\u9078\u64c7\u80a1\u7968\u4ee3\u78bc', data)\n    st.write('\u4f60\u9078\u64c7\u80a1\u7968\u662f: ', stock_code)<\/code><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"3_Setting_Upper_Bound_Lower_Bound_and_Grid_Interval_Tools\"><\/span>3. Setting Upper Bound, Lower Bound, and Grid Interval\u00a0Tools<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>\u9019\u908a\u5c07\u9810\u8a2d\u7684\u503c\u8a2d\u5b9a\u70ba\u4e0a\u754c\u503c\u70ba150\u3001\u4e0b\u754c\u503c\u70ba100\u3001\u7db2\u683c\u5340\u9593\u8a2d\u5b9a\u70ba<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>upper_bound = st.number_input('\u4e0a\u754c\u503c:',value=150)\nlower_bound = st.number_input('\u4e0b\u754c\u503c:',value=100)\ninterval = st.number_input('\u7db2\u683c\u5340\u9593:',value=10)<\/code><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Setting_up_Right-side_Charts_Datasets_and_Returns\"><\/span>Setting up Right-side Charts, Datasets, and\u00a0Returns<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>On the right side panel, we configure three tools to help us observe data trends, including buy and sell signal charts, datasets, and returns.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/www.tejwin.com\/wp-content\/uploads\/1QLNsvrkr8ng3JQ9sIC3eiQ.gif\" alt=\"\u53f3\u5074\u5716\u8868\u3001\u8cc7\u6599\u96c6\u3001\u5831\u916c\u7387\u7684\u8a2d\u7f6e\"\/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"1_Data_Processing\"><\/span>1. Data Processing<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>We have the stock name, start time, and end time on the left side. Here, we input these parameters into our TEJAPI database to select the data we need.<\/p>\n\n\n\n<p>Next, we create fields for buy and sell signals, filling the buy signal with data when the price falls and touches the grid and filling the sell signal with data when the price rises beyond the grid.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>stock_id = {stock_code}\n    gte, lte = {d1}, {d2}\n    tejdata= tejapi.get('TWN\/APIPRCD',\n                        paginate = True,\n                        coid = stock_id,\n                        mdate = {'gte':gte, 'lte':lte},\n                        chinese_column_name=True\n                        )\n    df = tejdata\n    df.reset_index(drop=True, inplace=True)\n    \n    # \u5275\u5efa Buy_Signal \u548c Sell_Signal \u5217\uff0c\u9810\u8a2d\u70ba False\n    df&#91;'Buy_Signal'] = False\n    df&#91;'Sell_Signal'] = False\n\n    # \u5728\u9069\u7576\u7684\u689d\u4ef6\u4e0b\uff0c\u5c07 Buy_Signal \u548c Sell_Signal \u8a2d\u7f6e\u70ba True\n    grid = list(range(lower_bound, upper_bound + interval, interval))\n    for i in range(1, len(df)):\n        for price in grid:\n            if df&#91;'\u6536\u76e4\u50f9']&#91;i-1] &gt; price &gt;= df&#91;'\u6536\u76e4\u50f9']&#91;i]:\n                df.at&#91;i, 'Buy_Signal'] = True\n            if df&#91;'\u6536\u76e4\u50f9']&#91;i-1] &lt; price &lt;= df&#91;'\u6536\u76e4\u50f9']&#91;i]:\n                df.at&#91;i, 'Sell_Signal'] = True<\/code><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"2_Trading_Signal_Charts\"><\/span>2. Trading Signal\u00a0Charts<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><br>First, set our tool options fields.<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code><code>tab1, tab2, tab3 = st.tabs(&#91;\"\u4ea4\u6613\u8a0a\u865f\", \"\u8cc7\u6599\u96c6\", \"\u6295\u8cc7\u7e3e\u6548\u8868\"])<\/code><\/code><\/pre>\n\n\n\n<p>\u5c07\u6536\u76e4\u50f9\u7e6a\u88fd\u6210\u80a1\u7968\u8d70\u52e2\u5716\u4e26\u5beb\u9032tab1\u7576\u4e2d\uff0c\u518d\u5c07\u8cb7\u8ce3\u8a0a\u865f\u52a0\u5165\u5728\u5716\u8868\u7576\u4e2d<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>with tab1:\n    st.title(stock_code)\n    fig = go.Figure()\n    fig.add_trace(go.Scatter(x=df&#91;'\u8cc7\u6599\u65e5'], y=df&#91;'\u6536\u76e4\u50f9'], name=stock_code))\n\n    # \u5275\u5efa\u7db2\u683c\uff0c\u5c07\u7dda\u689d\u984f\u8272\u8a2d\u7f6e\u70ba\u7070\u8272\n    for price in grid:\n        fig.add_shape(type=\"line\", x0=df&#91;'\u8cc7\u6599\u65e5'].iloc&#91;0], x1=df&#91;'\u8cc7\u6599\u65e5'].iloc&#91;-1], y0=price, y1=price, line=dict(color='gray'))\n\n    # \u52a0\u5165\u8cb7\u9032\u8a0a\u865f\u7684\u6563\u9ede\u5716\n    buy_signals = df&#91;df&#91;'Buy_Signal']]\n    fig.add_trace(go.Scatter(x=buy_signals&#91;'\u8cc7\u6599\u65e5'], y=buy_signals&#91;'\u6536\u76e4\u50f9'], mode='markers', name='Buy Signal', marker=dict(color='green', size=10, symbol='triangle-up')))\n\n    # \u52a0\u5165\u8ce3\u51fa\u8a0a\u865f\u7684\u6563\u9ede\u5716\n    sell_signals = df&#91;df&#91;'Sell_Signal']]\n    fig.add_trace(go.Scatter(x=sell_signals&#91;'\u8cc7\u6599\u65e5'], y=sell_signals&#91;'\u6536\u76e4\u50f9'], mode='markers', name='Sell Signal', marker=dict(color='red', size=10, symbol='triangle-down')))\n    fig.update_layout()\n    st.plotly_chart(fig)<\/code><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"3_Creating_Datasets\"><\/span>3. Creating\u00a0Datasets<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Input the data retrieved earlier into \u201ctab2\u201d and add a data download button.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>with tab2:\n    st.dataframe(df, height=500)  \n    @st.cache_data\n    def convert_df(df):\n        # IMPORTANT: Cache the conversion to prevent computation on every rerun\n        return df.to_csv().encode(\"utf-8\")\n    csv = convert_df(df)\n\n    st.download_button(\n        label=\"\u9ede\u6b64\u4e0b\u8f09\u8cc7\u6599\u7bc4\u4f8b\",\n        data=csv,\n        file_name=f\"{stock_code}\u80a1\u50f9\u8cc7\u6599.csv\",\n        mime=\"text\/csv\",)<\/code><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"4_Setting_Up_Trading_Data_Table_and_Investment_Performance_Table\"><\/span>4. Setting Up Trading Data Table and Investment Performance Table<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<ul class=\"wp-block-list\">\n<li>principal: Initial investment<\/li>\n\n\n\n<li>position: Number of shares held in the position<\/li>\n\n\n\n<li>cash&nbsp;: Amount of cash held<\/li>\n\n\n\n<li>order_unit&nbsp;: Number of shares traded in each transaction<\/li>\n<\/ul>\n\n\n\n<p>Here, we set the principle to 500,000 and the number of shares bought or sold in each transaction (order_unit) to 1000 shares. We will create a new dataset called trade_book to record transaction time, transaction cost, trading units, holding positions, and cash value. We will use the parameters in this dataset to calculate investment performance.<\/p>\n\n\n\n<p>The column names in the trade_book transaction table are as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>BuyTime: Buy time<\/li>\n\n\n\n<li>SellTime: Sell time<\/li>\n\n\n\n<li>CashFlow: Cash inflow\/outflow<\/li>\n\n\n\n<li>TradeUnit: Number of shares bought\/sold<\/li>\n\n\n\n<li>HoldingPosition: Current position<\/li>\n\n\n\n<li>CashValue: Remaining cash amount<\/li>\n<\/ul>\n<\/blockquote>\n\n\n\n\n\n<pre class=\"wp-block-code\"><code><code>with tab3:\n    st.title('\u4ea4\u6613\u6a21\u64ec')\n    \n    # \u521d\u59cb\u5316\u672c\u91d1\u548c\u4ea4\u6613\u7d00\u9304\u8868\n    principal = 500000\n    cash = principal\n    position = 0\n    order_unit = 1000  # \u6bcf\u6b21\u4ea4\u6613\u7684\u80a1\u6578\n    trade_book = pd.DataFrame(columns=&#91;'Coid', 'BuyOrSell', 'BuyTime', 'SellTime', 'CashFlow', 'TradeUnit', 'HoldingPosition', 'CashValue'])\n\n    st.write(\"\u672c\u91d1\uff1a\", principal)\n\n    # \u9032\u884c\u7db2\u683c\u4ea4\u6613\u4e26\u66f4\u65b0\u4ea4\u6613\u7d00\u9304\u8868\n    for i in range(1, len(df)):\n        cu_time = df&#91;'\u8cc7\u6599\u65e5']&#91;i]\n        cu_close = df&#91;'\u6536\u76e4\u50f9']&#91;i]\n        n_time = df&#91;'\u8cc7\u6599\u65e5']&#91;i - 1]\n        n_open = df&#91;'\u958b\u76e4\u50f9']&#91;i]\n\n        if position == 0 and df&#91;'Buy_Signal']&#91;i]:\n            # \u5224\u65b7\u662f\u5426\u9032\u884c\u8cb7\u9032\n            position += 1\n            order_time = n_time\n            order_price = n_open\n            friction_cost = (20 if order_price * order_unit * 0.001425 &lt; 20 else order_price * order_unit * 0.001425)\n            total_cost = -1 * order_price * order_unit - friction_cost\n            cash += total_cost\n            trade_book = trade_book.append({'Coid': stock_id, 'BuyOrSell': 'Buy', 'BuyTime': order_time, 'SellTime': None, 'CashFlow': total_cost, 'TradeUnit': order_unit, 'HoldingPosition': position, 'CashValue': cash}, ignore_index=True)\n\n        elif position &gt; 0 and df&#91;'Sell_Signal']&#91;i]:\n            # \u5224\u65b7\u662f\u5426\u9032\u884c\u8ce3\u51fa\n            order_price = n_open\n            cover_time = n_time\n            friction_cost = (20 if order_price * order_unit * 0.001425 &lt; 20 else order_price * order_unit * 0.001425) + order_price * order_unit * 0.003\n            total_cost = order_price * order_unit - friction_cost\n            cash += total_cost\n            trade_book = trade_book.append({'Coid': stock_id, 'BuyOrSell': 'Sell', 'BuyTime': None, 'SellTime': cover_time, 'CashFlow': total_cost, 'TradeUnit': -1 * order_unit, 'HoldingPosition': position, 'CashValue': cash}, ignore_index=True)\n            position = 0\n\n    st.write(\"\u4ea4\u6613\u7d00\u9304\u8868\uff1a\")\n    st.dataframe(trade_book)\n\n    # \u8a08\u7b97\u4ea4\u6613\u76f8\u95dc\u6578\u64da\n    overallreturn = ((cash - principal) \/ principal) * 100\n    num_trade = len(trade_book)\n    num_buy = len(trade_book&#91;trade_book&#91;'BuyOrSell'] == 'Buy'])\n    num_sell = len(trade_book&#91;trade_book&#91;'BuyOrSell'] == 'Sell'])\n\n    # \u8a08\u7b97\u5e73\u5747\u4ea4\u6613\u5831\u916c\n    avg_return_ = (trade_book&#91;'CashFlow'] \/ (trade_book&#91;'TradeUnit'] * trade_book&#91;'CashValue'])).mean() * 100\n\n    # \u8a08\u7b97\u5e73\u5747\u6301\u6709\u671f\u9593\n    trade_book&#91;'BuyTime'] = pd.to_datetime(trade_book&#91;'BuyTime'])  # \u5c07BuyTime\u8f49\u63db\u70badatetime\u683c\u5f0f\n    trade_book&#91;'SellTime'] = pd.to_datetime(trade_book&#91;'SellTime'])  # \u5c07SellTime\u8f49\u63db\u70badatetime\u683c\u5f0f\n    # \u8a08\u7b97\u6301\u6709\u671f\u9593\u4e26\u6392\u9664\u6389NaN\u548c\u8ca0\u503c\n    trade_book&#91;'HoldPeriod'] = (trade_book&#91;'SellTime'] - trade_book&#91;'BuyTime']).dt.days\n    trade_book&#91;'HoldPeriod'] = trade_book&#91;'HoldPeriod'].apply(lambda x: max(x, 0))  # \u5c07\u6301\u6709\u671f\u9593\u4e2d\u7684\u8ca0\u503c\u6539\u70ba0\n    avg_hold_period_ = trade_book&#91;'HoldPeriod'].mean()\n\n    # \u8a08\u7b97\u52dd\u7387\n    winning_rate = (len(trade_book&#91;trade_book&#91;'CashFlow'] &gt; 0]) \/ num_trade) * 100\n\n    # \u8a08\u7b97\u6700\u5927\u7372\u5229\u4ea4\u6613\u5831\u916c\u548c\u6700\u5927\u640d\u5931\u4ea4\u6613\u5831\u916c\n    trade_book&#91;'ReturnPercentage'] = (trade_book&#91;'CashFlow'] \/ (trade_book&#91;'TradeUnit'] * trade_book&#91;'CashValue'])) * 100\n    max_win = trade_book&#91;'ReturnPercentage'].max()\n    max_loss = trade_book&#91;'ReturnPercentage'].min()\n\n    # \u8a08\u7b97\u6700\u4f4e\u73fe\u91d1\u6301\u6709\u91cf\n    min_cash = trade_book&#91;'CashValue'].min()\n\n    # \u5448\u73fe\u4ea4\u6613\u76f8\u95dc\u6578\u64da\n    st.write('\u7e3d\u7e3e\u6548:', overallreturn, '%')\n    st.write('\u4ea4\u6613\u6b21\u6578:', num_trade, '\u6b21')\n    st.write('\u8cb7\u5165\u6b21\u6578:', num_buy, '\u6b21')\n    st.write('\u8ce3\u51fa\u6b21\u6578:', num_sell, '\u6b21')\n    st.write('\u5e73\u5747\u4ea4\u6613\u5831\u916c:', avg_return_, '%')\n    st.write('\u52dd\u7387:', winning_rate, '%')\n    st.write('\u6700\u5927\u7372\u5229\u4ea4\u6613\u5831\u916c:', max_win, '%')\n    st.write('\u6700\u5927\u640d\u5931\u4ea4\u6613\u5831\u916c:', max_loss, '%')\n    st.write('\u6700\u4f4e\u73fe\u91d1\u6301\u6709\u91cf:', min_cash)<\/code>\n\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Opening_STREAMLIT\"><\/span>Opening STREAMLIT<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>After setting everything up, you can start the STREAMLIT project by running \u201cstreamlit run <a href=\"http:\/\/app.py\" target=\"_blank\" rel=\"noreferrer noopener\">app.py<\/a>\u201d in the terminal.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>streamlit run app.py<\/code><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>This implementation uses the STREAMLIT package to present TEJAPI database data interactively in an app. It also incorporates a grid trading strategy. This allows readers to think about how to execute their own trading strategies in an app and add their own code to turn the analyzed data into more than just a report. In addition, <a href=\"https:\/\/api.tej.com.tw\/\" target=\"_blank\" rel=\"noreferrer noopener\">TEJ API<\/a> provides a wide range of Taiwan-related data on companies and financial markets, including finance, stocks, funds, macroeconomics, industries, and more. It also offers professional reports and research to assist companies in research, investment decision-making, and market forecasting.<\/p>\n\n\n\n<p>A friendly reminder, <strong>this introduction and subject matter are for reference only and do not represent any product or investment advice<\/strong>. In the future, we will also introduce using the TEJ database to construct various option models, so readers interested in options trading are welcome to purchase related solutions from <a href=\"https:\/\/eshop.tej.com.tw\/E-Shop\/index\" target=\"_blank\" rel=\"noreferrer noopener\">TEJ E-Shop<\/a> to build their own pricing models with high-quality databases.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Source_Code\"><\/span>Source Code<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/gist.github.com\/tej87681088\/a454b23fa33244d9cdad450ecd7c12cd\" class=\"ek-link\" target=\"_blank\" rel=\"noopener\">Github<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Extended_Reading\"><\/span>Extended Reading<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a aria-label=\"Django\u8207TEJ API (Part 1) (opens in a new tab)\" href=\"https:\/\/www.tejwin.com\/insight\/%E3%80%90%E8%B3%87%E6%96%99%E7%A7%91%E5%AD%B8%E3%80%91django%E8%88%87tej-api-part-1\/\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\"><a aria-label=\" (opens in a new tab)\" href=\"https:\/\/www.tejwin.com\/en\/insight\/tquant-lab-momentum-trade\/\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\">\u3010Quant\u3011TQuant Lab Momentum Trade<\/a><\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.tejwin.com\/insight\/tej-api-%e9%81%87%e4%b8%8astreamlit-app\/\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\"><a href=\"https:\/\/www.tejwin.com\/en\/insight\/tquant-lab-price-deviation-ratio-trading-strategy\/\" class=\"ek-link\">\u3010Quant\u3011TQuant Lab Price Deviation Ratio Trading Strategy<\/a><\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Related_Links\"><\/span>Related Links<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/tejtw\/TQuant-Lab\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\">TQuant Lab Github<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In previous tutorials, we learned how to create our own STREAMLIT App. For more details, you can refer to this article. In this article, we will use the TEJ API database to connect with the STREAMLIT package and implement a grid trading strategy. We will use tools such as date selection, dropdown menus, and numerical selectors to interact with charts and tables, making the data an interactive app.<\/p>\n<p>Grid trading is a trading strategy that selects a range by setting two parameters, the upper bound and the lower bound. We divide the stock price into grid intervals, buying stocks when the price falls and touches the lower grid, and selling stocks when the price rises and exceeds the upper grid.<\/p>\n<p>This strategy is a lazy strategy that doesn\u2019t require much manual operation. It can also profit from price fluctuations. However, there are a few points to note which is the efficiency of capital utilization will be lower than manual trading.<\/p>\n","protected":false},"featured_media":17908,"template":"","tags":[2572,2988,3008,2735],"insight-category":[690,50,3509],"class_list":["post-18983","insight","type-insight","status-publish","has-post-thumbnail","hentry","tag-data-analysis","tag-quantitative-analysis","tag-tejapi-quant","tag-2735","insight-category-data-analysis","insight-category-fintech","insight-category-fintech-en"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight\/18983","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight"}],"about":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/types\/insight"}],"version-history":[{"count":1,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight\/18983\/revisions"}],"predecessor-version":[{"id":20880,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight\/18983\/revisions\/20880"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/media\/17908"}],"wp:attachment":[{"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/media?parent=18983"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/tags?post=18983"},{"taxonomy":"insight-category","embeddable":true,"href":"https:\/\/www.tejwin.com\/en\/wp-json\/wp\/v2\/insight-category?post=18983"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}