---
# System prepended metadata

title: "\U0001F331 韭菜是割還是哥！？"
tags: [side project]

---

:::warning
# 🌱 韭菜是割還是哥！？
### 🌱 🌱 從零開始打造雲端交易機器人🤖 + dashboard app 👀
:::

###### tags: `side project`

## 文件大綱(文長請由左側導覽bar跳轉至您有興趣的段落)
1. Project整體概覽
2. 尋覓合適交易演算法
3. 交易機器人實作(dataflow、DB設計..)
4. 交易機器人dashboard實作
5. AWS雲端部署與自動節能(省錢)設定
6. 其他重要連結如下：
- [dashboard成品](http://15.165.161.231:8501/)
    - 我用了最新版的streamlit app，目前測試mac用chrome，iphone 11以上用chrome，android沒特別限制用chrome都可順利開啟此app，但windows目前會出錯，官方表示有在修復，若開不了請先看底下影片demo 
    - 因近日交易低迷，各機器人僅有一日有做到交易(美國加息會議那天)，故有先放一些pseudo data來demo app功能
- [雲端交易機器人影片demo](https://www.youtube.com/watch?v=CaWtj_EcH_4)
- [dashboard app影片demo](https://www.youtube.com/watch?v=CyIGc61JsNw)
- [Github連結](https://github.com/enchichen1107/trading_bot)




## 💁🏻‍♀️ Project整體概覽
* **製作動機**
    * 加密貨幣市場有個很大的優勢，就是交易門檻相對較低，幾十塊美金即可入場交易，這對於想練習投資的小白而言無疑是一大佳音。然而～加密貨幣市場瞬息萬變，幣圈一天、人間一年，如果沒有相當的心理素質，很容易追漲殺跌，成為被割下的韭菜。但人非聖賢，孰能100%理性？故，敝人將嘗試以交易機器人的方式，真正的、無情的落實戰術，並用dashboard app呈現機器人交易表現，來看看一季後的收成如何
* **整體實作流程**
    1. 回測歷史資料找出合適的交易演算法
    2. 實作交易機器人
    3. 實作dashboard app
    4. 雲端部署與自動節能設置
![](https://i.imgur.com/wPRhWjv.jpg)

## 🐾 尋覓合適交易演算法
* **比特幣大盤概覽**
    * 首先，大家需要先知道，加密貨幣市場的大盤就是比特幣(簡稱btc，全名bitcoin)，而比特幣對於技術分析來說也是比較好的標的。因為相對於其他山寨幣(小幣)，比特幣比較不會被壟斷操作。故本篇都先以btc比特幣對usdt(一種對標美金的幣，1 usdt約等於1 usd)的交易對為主。
    * 接下來我們正式來看比特幣大盤這三年的變化，探索一下所謂HODL(單純抱著比特幣沒有進一步操作)是否能獲利？
    * 如果你在2019年進入這個市場～Y軸會是你的累計收益率變化，此時的你應該會對比特幣抱持信仰，因為就算抱著不動三年，收益也有三.xx倍
![](https://i.imgur.com/8SwYttW.png)
    * 如果你在2020年進入這個市場～Y軸會是你的累計收益率變化，此時的你應該會對比特幣抱持信仰，因為就算抱著不動兩年，收益也有三.xx倍
![](https://i.imgur.com/VnedwuV.png)
    * 如果你在2021年進入這個市場～Y軸會是你的累計收益率變化，此時的你應該會對比特幣失去信仰，因為抱著不動一年，收益不增反減！！！
![](https://i.imgur.com/hjWpoNz.png)
    * 我們把這三個進場時間點的累計收益畫在一張圖比較一下，就能更深刻的感受到...HODL只有牛市可行啊！
![](https://i.imgur.com/xSh2TCd.png)
* **交易演算法介紹**
    * 這邊跟大家介紹的是投資小白入門款breakout法則，它的概念很簡單，就是在價格有明顯向上突破且帶交易量時，預期後市看漲故買入，在價格有明顯向下突破且帶交易量時，預期後市看跌故賣出。一般來說價格是否有突破會以是否破過去15到20根K線的滾動平均最高/最低價來斷定，而有沒有帶交易量則是看有沒有大於過去15到20根K線的滾動平均最高交易量的n倍(n是個可調控的參數)。至於離開交易的時機點則利用上一根K線的收盤價+/-ATR來和這輪K線的最高/低價做比較來決定。舉例：如果是做買入，但本輪K線最低價已經低於上一根K線的收盤價-ATR，則表示行情可能要開始逆轉，需進行離場。
    * 至於什麼是[ATR](https://www.tradingview.com/support/solutions/43000501823-average-true-range-atr/#:~:text=Definition,price%20gaps%20or%20limit%20moves.)？ATR為average true range的簡稱，它定義了幣價在某一時間區間內的真實波動。波動的計算是取下列三個數值的最大值，接著再依照想看的時間區間做滾動平均：
        * 1.今日最高價-最低價
        * 2.今日最高價-昨日收盤價的絕對值
        * 3.今日最低價-昨日收盤價的絕對值
* **Breakout演算法回測**
    * 以下這張圖是調用Binance(目前最大的現貨交易平台)的現貨API撈取比特幣歷史15minK線圖後，用預設20根K線和1.5倍交易量做的回測結果，並將其和HODL做比較。看完可明顯感受..痾，表現居然不如HODL！！！
![](https://i.imgur.com/gUFMGQr.png)
    * 因此我們需要來優化一下參數，試試不同組合的結果能否改善收益率，我們試著放入7到20根，1.2到2倍的各種可能性後，結果如下   
    * 累計收益率最高(6.42)的是八根+1.9倍交易量突破
![](https://i.imgur.com/yGQxqxv.png)
    * CAGR([複合年均增長率](https://rich01.com/what-is-cagr/))最高(0.86)的是八根+1.9倍交易量突破
![](https://i.imgur.com/9RKUiti.png)
    * sharpe([夏普比率](https://rich01.com/what-sharpe-ratio/#:~:text=%E5%A4%8F%E6%99%AE%E7%8E%87%E5%A4%A7%E7%B4%84%E8%90%BD%E5%9C%A8,%E9%82%A3%E5%B0%B1%E9%9D%9E%E5%B8%B8%E5%84%AA%E7%A7%80%E4%BA%86%E3%80%82))最高(2.38)的是九根+1.9倍交易量突破(一般來說1.5的夏普比率已經很不錯)
![](https://i.imgur.com/DgjfRQg.png)
    * Max drawdown([最大回撤](https://www.stockfeel.com.tw/%E6%9C%80%E5%A4%A7%E5%9B%9E%E6%92%A4-max-drawdown-%E7%AD%96%E7%95%A5%E7%AE%A1%E7%90%86/))最低(0.13)的是十三根+1.9倍交易量突破
![](https://i.imgur.com/I65sHBN.png)
    * 綜合以上結果，這裡選定九根+1.9倍交易量突破作為優化解，雖然它的累計收益率和CAGR稍低於八根+1.9倍交易量突破，但最大回撤卻好很多(0.15 vs 0.2)    
    * 下圖為優化後的版本和HODL比較，終於勝出啦！！
![](https://i.imgur.com/AfkjeXp.png)
    * 再看一張HODL vs 預設數值 vs 優化版本的比較圖
![](https://i.imgur.com/loBMTYn.png)
    * 接下來呢，我們改用超短線5min K線 scalping(挖到一點小利潤就逃)來回測breakout的方式看看。因為用超短線，故用一年內的資料來回測，畢竟時間太久會很失真。下圖為預設數值(7根K線+1.5倍)回測結果，看來是比HODL好，但幾乎沒什麼獲利到，趨勢線幾乎是平的
![](https://i.imgur.com/d1bci5q.png)
    * 一樣，來優化看看不同的組合。這裡有蠻明顯的勝出者，15根K線+2倍交易量突破，回撤小，收益又高，一年共有兩千多次的交易機會
![](https://i.imgur.com/uv0Z944.png)
    * 接著來看看優化後的比較圖。簡直完勝HODL和預設值啊！
![](https://i.imgur.com/HV2Lqgw.png)
* **回測小結論**
    * 優化後的版本交易表現都明顯勝出HODL與預設版本，這告訴我們沒有全仰賴預設，動點手優化是有好處的！
    * HODL基本上就是一個牛市中的懶人賺錢法，但像現在熊市開始後只能虧本離場QAQ即便是熊市中的現貨交易，幣價還是會有波動的時候，靠著技術分析還是有機會賺到錢的
    * breakout還是適合波動大的投資標的，如果很穩健沒什麼波動反而賺不到錢。但以幣圈來說就很適合，幣圈沒有漲跌停板，波動起來很驚人的
    * 最後，歷史資料回測能賺錢不見得代表未來也能賺錢，有可能只是overfit...故接下來我們來把演算法寫成交易機器人，並利用binance提供的testnet來做paper trading(假錢交易)來測試一季看看效果如何！

## 🤖 交易機器人實作
以下是整個系統的設計圖，我們的目標是拆成交易機器人、dashboard app、AWS雲端部署三個區塊來談完這張大圖。首先，我們來談黃色資料庫左半邊這一區
![](https://i.imgur.com/2zVWb38.jpg)

* **機器人功能概覽**
    * 機器人由演算法和資料驅動，其最重要的工作就是live stream幣價資料，做分析，一有進場時機點就透過binance testnet api下單
    * 其他功能為停損寄信警示、完成交易時一併將交易資訊送進資料庫，以供未來dashboard app做視覺化處理
* **機器人dataflow設計**
    * **交易演算法所需資料**
        * **歷史幣價資料**：因為演算法會需要前幾根K線的資料才能啟動，故會需要先用api撈資料進來。然後這邊需要注意binance testnet雖然有幣價資料，但因為交易量少，它的最高、最低價與真實資料嚴重脫鉤，故還是建議用binance一般的幣價api撈就好。至於需不需要撈進資料庫放著，敝人認為是不需要，因為使用率極低，只有在第一輪K線的交易判斷中會用到，之後都會用實時幣價資料來分析
        * **實時幣價資料**：這是資料流裡面我覺得比較難搞的部分。因為要實時交易，如果長時間一筆一筆用api打進來，我這ip可能會快就會因為binance api政策的api次數限制被ban掉。後來我找到binance有提供websocket可以實時串入幣價資料，它就沒有api call的次數限制，只是binance websocket的文件我覺得有點霧裡看花(可能功力太差ˊˋ)，再後來我又找到一個好用的python binance api wrapper，但要注意它目前就1.0.15版本的websocket沒有問題可以用，新版本我測過會噴錯。以下附上我在弄live stream price data的重點參考資料
            * [binance github](https://github.com/binance/binance-spot-api-docs/blob/master/user-data-stream.md)
            * [python binance github](https://github.com/sammchardy/python-binance/blob/master/docs/websockets.rst)
            * [python binance doc](https://python-binance.readthedocs.io/en/latest/_modules/binance/streams.html#ThreadedWebsocketManager.start_user_socket)
        * 以上資料梳理完畢後，演算法就可以實時分析幣價資料並在適當時機點call binance testnet api下單
    * **交易資料庫設計**
        * 我其實蠻猶豫這一節要放在哪談，因為資料庫要放什麼還是基於應用端所需的資料邏輯。但因為資料是在機器人這邊打進去的，故還是決定先在這裡談一部分。
        * **首先，建立資料庫的必要？**
            * 在此有必要，如果想看到testnet測試一個月以上的結果就會需要。因為testnet固定每個月會清空所有過去交易資訊...
        * **要放哪些資料？**
            * 根據dashboard的需要，我只放最根本的交易資訊進去。其他衍生資料，例如累計收益率等，全部不放，到dashboard要呈現時再算。這樣雖然到時候dashboard呈現會比較慢，但好處就是我隨時想要改交易表現的指標時，只要改完算法的code就了事。那最根本的資料有哪些呢？
            * 基本上所有交易表現指標都是用進出場的時間點的價位來做計算，所以我想最基本要存的就是交易時間、交易方向(買或賣)、交易對、交易價位。只要有這些資訊，那要算什麼都不會有太大問題。以上，我們有了第一張table：trade_record。
            * 接下來還想放的就是交易帳戶的資產，透過dashboard看資產變化我覺得是很直覺、直接的呈現交易成果。這邊我想基本要存的也很直覺，資產更新時間、資產別、數量。以上，我們有了第二張table：asset。
            * 再來這個問題就是我們有兩隻交易機器人，他們的交易資訊要存在同一張table，然後用一個column例如bot幾號來區別嗎？還是用不同張table來紀錄？我這邊是考慮到dashboard呈現時，我希望可以有各機器人的詳細交易表現數據分頁。基於這個應用，敝人認為分開保存會比較好，因為在調資料時少一層filter速度會比較快。所以，以上我們就有四張tables了，asset1, asset2, trade_record1, trade_record2。
            * 最後，考慮到未來更有交易經驗時可能會想嘗試除了比特幣以外的交易對。但其他交易對，我比較不熟，但對全名會有印象，故也放上了交易對簡稱和全名的對照表names。
            * 目前所有tables都為BCNF，就是簡單、乾淨的交易和資產紀錄為主。所有資料都為atomic，candidate key為交易/更新時間，只能從candidate key uniquely define其他fields。
            * 到這裡，tables告一段落，以下為各table的截圖(因bot2與bot1的table基本雷同，故以bot1為例)，應該看得到data type和pk。另外，search key這邊我沒有特殊要求就用default pk即可
            * 交易對簡稱和全名的對照表names
![交易對簡稱和全名的對照表names](https://i.imgur.com/UTP4r8n.png)
            * trade_record1
![](https://i.imgur.com/7rE9ftU.png)
            * asset1
![](https://i.imgur.com/cGrLDKS.png)
        * **資料怎麼更新？**
            * 敝人認為流程上交易做完順便寫進去是最順的，而剛好binance也有user data的websocket，我就利用這個socket來即時更新資料庫。所以流程就是，機器人做交易，user data websocket回傳交易資訊json檔，篩出需要寫進資料庫的資訊，最後insert into各tables。詳細code請見[github link](https://github.com/enchichen1107/trading_bot)(either bot1.py或bot2.py皆可)。
        * **資料怎麼調用？**
            * 這部分我們留待dashboard app討論
    * **停損寄信警示**
        * 這個是user data websocket的第二個應用，一收到帳戶資產變化，就來順便檢查資產有沒有蒸發過頭，一有異常就寄信警告。我想python寄警示信的應用是蠻常見的，這裡附上我參考的[教學文](https://www.learncodewithmike.com/2020/02/python-email.html)。寄信的測試結果如下圖：
![](https://i.imgur.com/hN5vf9o.png)



##  📊 交易機器人dashboard實作
我們現在來談黃色資料庫右半邊的dashboard app
![](https://i.imgur.com/2zVWb38.jpg)
* 這邊遇到第一個問題是用什麼方法呈現比較好？要寫前端三語嗎？還是有其他更適合的方式？後來我想到，像R有shiny可以視覺化呈現分析成果，那python應該也會有吧？結果一查就查到streamlit，它真的是可以美美的呈現分析結果！上手難度也還好，有一點前端基礎，跟著做完一輪tutorial就會了。唯一美中不足大概就是它的最新版本有些相容issue..但因為最新版本有multipages的功能，所以..我還是用下去了..
* [streamlit gallery](https://streamlit.io/gallery)
* [streamlit tutorial](https://docs.streamlit.io/knowledge-base/tutorials)
* **dashboard app運作流程**
    * **交易資料庫資料調用**
        * 基於app一打開的預設交易時間區間呈現就是從開始到末了，所以app一開頭就需要先進資料庫cur.fetchall()，select * from xxx table撈出交易和資產資訊。詳細code請見[github link](https://github.com/enchichen1107/trading_bot)(在app資料夾內的首頁，和app資料夾內的pages資料夾內的helper.py最一開始的段落就是資料調用)。
    * **交易表現指標運算**
        * 撈完資料後自然是做一些運算，這些交易表現指標和歷史資料回測那部分有重疊，就不贅述，需要reference的話，回測那一part有附連結，可左邊選單跳過去看
    * **指標呈現**
        * 由於本app主要user就是敝人，我看資料喜歡從各個角度切入，故呈現方式我用了數個方式～運算後的綜合指標、圖表、dataframe

## 💰 AWS雲端部署與自動節能(省錢)設定
終於，來談遍佈整張圖的AWS系列們(還有右下角那三個自動化設定)，這裡會切成幾個部分
* AWS EC2部署機器人
* AWS EC2部署dashboard app
* EC2與RDS的connection
* 自動節能設定

![](https://i.imgur.com/2zVWb38.jpg)

* **AWS EC2部署機器人**
    * 首先，這裡先來決定一個問題，到底要開幾個EC2放機器人？我理想中是用一份2vcpu的EC2方案，然後同時run兩隻機器人，後來發現..不行，太貴啦！再加上，敝人的learner lab錢錢已所剩無幾，故還是選擇用兩個最便宜的方案各放一隻機器人。
    * 再來處理code中各種秘密，DB秘密、api key秘密、信箱秘密..這裡是調用AWS的secret manager來處理這些秘密，[AWS秘密管理教學文](https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_examples.html)我覺得是蠻清楚的，我自己的做法是直接在製造秘密時把可以access此秘密的role放入Labrole，然後EC2建立時也用這個role，如此便能順利取得秘密
    * 最後部署，我的作法基本上就是ssh從local連線到EC2之後，把code放過去，然後設定時讓它run(最後自動節能設定會提到)
* **AWS EC2部署dashboard app**
    * steamlit其實有自己的[cloud](https://docs.streamlit.io/streamlit-cloud/get-started/deploy-an-app)可以部署，但為了熟悉AWS，我還是放AWS了，這篇[教學文](https://towardsdatascience.com/how-to-deploy-a-streamlit-app-using-an-amazon-free-ec2-instance-416a41f69dc3)算是很詳盡的寫了如何部署，這裡不贅述
    * 這裡需要特別注意的點，我認為是ip..因為如果要固定public ip是要額外付費的Orz 基於learner lab快沒錢，我後來想了一個折衷方案，就是我額外申請了AWS的帳號，用它的免費方案來放EC2的app，這個免費方案基本上可以run一個最便宜的EC2一整年沒問題，換句話說就不用關EC2，意即它的public ip就不會變，只要沒有關掉又重開它
* **EC2與RDS的connection**
    * 這裏要來處理資料寫入與讀出資料庫的問題了，怎麼和AWS上的資料庫溝通，[看完這篇AWS教學文](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ConnectToPostgreSQLInstance.html)我想就差不多。基本上要注意的就是，一開始建立資料庫時就要先想好你的資料庫有沒有要和AWS VPC(私有雲)以外的端點溝通，有的話建立時就要先選 <font color="#FF8733">***==public==***</font>
* **自動節能(省錢)設定**
    * 這邊的節能設定是針對兩隻在EC2的交易機器人，因為RDS和app被我放到免費方案去了，故無須擔憂經費
    * **自動排程開關EC2**
        * AWS在這塊也有出[教學文一](https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-eventbridge/?nc1=h_ls)、[教學文二](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html#eb-cron-expressions)。如果是比較複雜的系統，牽動更多AWS instances，AWS還有出[instance scheduler](https://aws.amazon.com/tw/solutions/implementations/instance-scheduler/)，但這要付費，所以我這邊還是用了cloudwatch+lambda的組合(很省經費)來達到自動排程開關EC2的目的
        * 以下放個暫停EC2的lambda調用紀錄，讓大家看一下，截至今它真的已經run了四天(如果有看youtube demo影片就會知道我為何特別說這個..)
![](https://i.imgur.com/2Kdi92I.png)
    * **EC2內的自動排程**
        * EC2能自動定時開關後，我們還是需要在EC2內讓它定時自動啟動交易，這邊的方法就看EC2作業系統用什麼，用windows的話就有內建的工作排程器可以用，但windows比linux的EC2貴，故我選了linux，然後用[crontab來達到排程](https://blog.gtwang.org/linux/linux-crontab-cron-job-tutorial-and-examples/)目的。
    * **啟動AWS費用預警**
        * 基本上這邊最重要的就是要意識到東西在雲端跑著跑著，不知不覺可能會費用突破天際，就算已經事先算好可能花費(茶～)，因為有些錢會在不太容易注意到的地方...例如：AWS EC2已經暫停，但如果EC2有放EBS一樣會收錢錢。所以保險起見還是用個費用預警！而費用預警還蠻容易設置的，看看[AWS費用預警教學](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html)即可～特別要注意的大概就是要去填寫的收取警示信箱啟動警示服務，搞定後就會在AWS Cloudwatch警示中看到這個囉～
![費用預警圖](https://i.imgur.com/uOJuTV7.png)
* 最後這一區放一些過程中有參考的資料們
* api相關
    * https://stackoverflow.com/questions/70027278/how-to-extract-all-crypto-symbols-from-coinmarketcap
* python相關
    * https://stackoverflow.com/questions/71216795/calculate-sum-for-column-in-dataframe-using-pandas
    * https://www.delftstack.com/howto/python-pandas/how-to-create-dataframe-column-based-on-given-condition-in-pandas/
* streamlit做圖相關
    * https://altair-viz.github.io/gallery/layered_area_chart.html
* 技術指標相關
    * https://www.freqtrade.io/en/stable/
    * https://technical-analysis-library-in-python.readthedocs.io/en/latest/
    * https://www.udemy.com/course/algorithmic-trading-with-python-and-machine-learning/
    * https://www.udemy.com/course/algorithmic-trading-quantitative-analysis-using-python/













