{"id":59,"date":"2025-03-22T10:42:57","date_gmt":"2025-03-22T17:42:57","guid":{"rendered":"http:\/\/www.ashwang.net\/?p=59"},"modified":"2025-03-22T10:42:57","modified_gmt":"2025-03-22T17:42:57","slug":"building-a-6-factor-quantitative-trading-model-for-bitcoin-using-python","status":"publish","type":"post","link":"http:\/\/www.ashwang.net\/index.php\/2025\/03\/22\/building-a-6-factor-quantitative-trading-model-for-bitcoin-using-python\/","title":{"rendered":"Building a 6-Factor Quantitative Trading Model for Bitcoin Using Python"},"content":{"rendered":"\n<p>This tutorial walks you through building a true 6-factor Bitcoin trading strategy from scratch using Python. By leveraging classic technical indicators\u2014EMA, MACD, RSI, KDJ, CCI, and OBV\u2014we construct a signal classification model that outputs Buy, Sell, or Hold decisions.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Load Bitcoin Data<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>btc_data = pd.read_csv(\"btc_data.csv\", parse_dates=&#91;'Open time'])\nbtc_data.set_index('Open time', inplace=True)\nbtc_data.rename(columns=lambda x: x.lower(), inplace=True)<\/code><\/pre>\n\n\n\n<p>We load 15-minute interval BTC price data and set the timestamp as the index.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Add Technical Indicators<\/h2>\n\n\n\n<p>Using the <code>pandas_ta<\/code> library, we calculate the following indicators:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>EMA<\/strong>: 6, 18, and 60-period Exponential Moving Averages<\/li>\n\n\n\n<li><strong>MACD<\/strong> &amp; Signal Line<\/li>\n\n\n\n<li><strong>RSI<\/strong> (14-period)<\/li>\n\n\n\n<li><strong>CCI<\/strong> (14-period Commodity Channel Index)<\/li>\n\n\n\n<li><strong>KDJ<\/strong> (Stochastic Oscillator)<\/li>\n\n\n\n<li><strong>OBV<\/strong> (On-Balance Volume)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>import pandas_ta as ta\n\ndf&#91;'EMA_6'] = ta.ema(df&#91;'close'], length=6)\ndf&#91;'EMA_18'] = ta.ema(df&#91;'close'], length=18)\n# ...\ndf&#91;'OBV'] = ta.obv(df&#91;'close'], df&#91;'volume'])\ndf.dropna(inplace=True)<\/code><\/pre>\n\n\n\n<p>Each factor represents a different dimension of market behavior\u2014momentum, volume flow, or sentiment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Price Prediction Model<\/h2>\n\n\n\n<p>We use the technical indicators to predict the next period\u2019s closing price:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>X = df&#91;&#91;\"EMA_6\", \"EMA_18\", ..., \"OBV\"]]\ny = df&#91;'close'].shift(-1)<\/code><\/pre>\n\n\n\n<p>Train a regression model (e.g., linear regression):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from sklearn.linear_model import LinearRegression\n\nmodel = LinearRegression()\nmodel.fit(X_train, y_train)<\/code><\/pre>\n\n\n\n<p>You can include the predicted price (<code>Predicted_Close<\/code>) as an additional feature in the classification step.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Signal Classification Model (Buy\/Sell\/Hold)<\/h2>\n\n\n\n<p>We define trading signals based on the following rule-based logic:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>y = np.where(\n    (EMA_6 &gt; EMA_18) &amp; (MACD &gt; MACD_signal) &amp; (RSI &gt; 30) &amp;\n    (K &gt; D) &amp; (CCI &gt; 100) &amp; (OBV &gt; OBV.shift(1)), 1,\n    np.where(\n        (EMA_6 &lt; EMA_18) &amp; (MACD &lt; MACD_signal) &amp; (RSI &lt; 70) &amp;\n        (K &lt; D) &amp; (CCI &lt; -100) &amp; (OBV &lt; OBV.shift(1)), -1, 0\n    )\n)<\/code><\/pre>\n\n\n\n<p>Then, train a classifier to predict these Buy\/Sell\/Hold labels:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from sklearn.ensemble import RandomForestClassifier\n\nmodel = RandomForestClassifier(max_depth=5)\nmodel.fit(X_train, y_train)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Visualizing Strategy Performance<\/h2>\n\n\n\n<p>Using Plotly, we visualize:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Actual vs. Predicted price<\/li>\n\n\n\n<li>Buy signals (green triangle)<\/li>\n\n\n\n<li>Sell signals (red inverted triangle)<\/li>\n\n\n\n<li>Hold signals (yellow dots)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>fig.add_trace(go.Scatter(..., name='Buy'))\nfig.add_trace(go.Scatter(..., name='Sell'))\nfig.add_trace(go.Scatter(..., name='Hold'))<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 Technical factors based on classic indicators: MACD, KDJ, OBV, etc.<\/li>\n\n\n\n<li>\ud83d\udd04 Labels generated using combined conditions (rule-based logic)<\/li>\n\n\n\n<li>\ud83e\udd16 Classification powered by machine learning (Random Forest)<\/li>\n\n\n\n<li>\ud83d\udcc8 Visual outputs help evaluate strategy performance and logic<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Download &amp; Connect<\/h2>\n\n\n\n<p>The complete code and dataset will be available on GitHub soon.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial walks you through building a true 6-factor Bitcoin trading strategy from scratch using Python. By leveraging classic technical indicators\u2014EMA, MACD, RSI, KDJ, CCI, and OBV\u2014we construct a signal classification model that outputs Buy, Sell, or Hold decisions. Step 1: Load Bitcoin Data We load 15-minute interval BTC price data and set the timestamp [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-59","post","type-post","status-publish","format-standard","hentry","category-tutorial"],"_links":{"self":[{"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/posts\/59","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/comments?post=59"}],"version-history":[{"count":1,"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/posts\/59\/revisions"}],"predecessor-version":[{"id":60,"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/posts\/59\/revisions\/60"}],"wp:attachment":[{"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/media?parent=59"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/categories?post=59"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.ashwang.net\/index.php\/wp-json\/wp\/v2\/tags?post=59"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}