潮流特區

最新文章

推坑SFC的神作

手機‧電玩
MacauYeah・2024-09-03

因為年紀漸大,筆者玩遊戲的機會越來越少。一方面是因為家庭,一方面則是因為身體大不如前,腦袋開始跟不上3D遊戲的場境,常常不是玩一玩就累了,就是玩一玩就暈了,那怕連手遊都一樣。 所以筆者現在什少會再開新坑試新世代遊戲,反而專注在舊世代中,體驗一下過去的名著。值得一提的是,過去的遊戲體量通常比較少但完整,對於繁忙的生活節奏,是適合的。相比手遊,舊世代的遊戲更無抽蛋要素,更沒有那種玩個空虛的感覺。所以若然大家主機有買會員,趁會籍到期之前,快試一試那些年被你跳過的遊戲,應該有所收獲。 今日筆者就選了NS online會員的SFC舊遊戲,《薩爾達 眾神的三角力量》。只要大家有NSO,應該都可以順利重玩這個遊戲。 向大家推坑這遊戲的原因主要有幾個。 薩爾達 Switch 兩作稱霸天下。過去的作品,很值得一試。 眾神的三角力量是平面遊戲,不會暈,而且 Switch 隨時待機,玩玩停停沒有壓力。 玩後的優點: 那個古早的年代,已經發展出到處鼓勵四處探索的玩法。那怕只是2D平面,都感覺到世界的大。 攻略好找好看。薩爾達在 Switch 中的最後兩,好玩歸好玩,但攻略真的難攪,難以用文字來表達。即使各大出版社如何編制圖文包,還不如直接看影片攻略來得直接。眾神的三角力量,那怕筆者不看圖,筆者也知道攻略制作人想表達的意思和方向。不知道下一步去哪?不用怕,看一看網上攻略就攪掂。 偏向動作遊戲,穿插少量劇情。筆者過去都是接觸以劇情量為主的JRPG,以現在的生活形態,要好好地讀完一個新的JRPG故事真的很難。 沒有壓力。這真的很重要。Switch 兩代,都有一個很麻煩的資源系統。武器、道具、盾,都是會快速消耗的。除非大家對操作很有信心,不然每次戰鬥,那怕打贏了,也會覺得消耗過多,選擇重讀存檔重打。這樣的遊戲玩下去很有壓力,跟魂系遊戲有得比。多磨幾次,人也會累。但SFC 舊作,只有副武器為消耗性。你的劍和盾,可以一直用,副武用光,誰怕誰。 參考連結: 筆者遊玩時看的攻略(https://lasjargon.blogspot.com/2014/12/legend-of-zelda-link-to-past-chapter01.html?m=1),雖然覺得不全,但至少讀得懂 由 本封面圖像可由任天堂處取得。, Fair use, https://zh.wikipedia.org/w/index.php?curid=7663843

為何Python這麼熱門?

科技新知
MacauYeah・2024-08-27

在資料處理、資料科學領域,什麼是最近的AI模型,Python都是做這些事的熱門選擇。對於以前從未用過Python來處理業務的筆者來講,實在不懂為何Python會那麼大熱。不過最近,筆者實戰過後,真心覺得它是提高生產力的重要工具,而且並不限於資料科學上面,一些簡單的腳本操作也是很有優勢的。 筆者前述有討論過 型別對程式語言的重要性,到現時這一刻,筆者都會覺得【型別】是有助於長期的程式開發。而Python這個語言,大部份人都會介紹它是動態語言,可以使用弱型別,然後,就沒有其他講法了。動態弱型別,筆者一直都不認為它的根本上的原因。就像Javascript一樣,它亦發展出類靜態強型別的Typescript版本,而且它亦不因此而被人棄用。所以Python的強大,動態語言並不一最重要的原因,它也可以模疑寫出有規有距的type hinting。 或者用另一個方向問,大家覺得 Excel / SpreadSheet 好用嗎?它們可以很簡易地做出資料計算、篩選。而且可以一邊做,一邊調整公式。例如要大家做一個陣列的總和,大家會想打開一個Javascript,初始化陣列的每個數字,然後寫個For迴圈去計算總和嗎?還是打開 Excel / SpreadSheet,打下一欄或一列的數字,然後叫出Sum函數?筆者一定會選擇後者,不單止因為寫函數比較方便,那怕之後要調整數字,也比較方便。 大家有感受到差異嗎?筆者想表達的是,在操作 Excel / SpreadSheet 我們並不是整個程式重新執行一次,我們是修改完一部份,那上看到結果。但傳統的語言,例如C、Java、那怕是Javascript,我們都難以局部地更新或執行特定某一個區塊。那怕是現在我們有hot reload,但其實我們編寫的思維,都是讓我們完整執行起一個頁面,再人手輸入,看結果。如果我們只想運行某個單一Function函數,我們只能寫test case測試,但寫test case又是一個很大的入門門檻。 但大家如果看看Python,在古早的年代,Python已經有Python shell,那就像是Linux Shell或Window CMD一樣,可以一邊寫腳本,一邊看結果。寫了10行的程式,發現在第10行引用第5行的部份有問題,修正並執行第5行後,就可以回來馬上重跑第10行的語句,就馬上有結果了。第6至9行,因為沒有關聯性,就不需要逐一重新執行,那是多麼的方便阿。道理上,我們若沒有完整執行整個程式,可能還是有一些盲點,開發重要的,需要長期維護的程式,還是要像傳統一樣,有test case,有程式進入點,整個運行。但對於臨時性的操作,看看效果,我們實在無必要寫一個原整程式。 舉個例子,假如我們臨時有需要,要取得某個政府網站的即時數據,例如澳門的停車場資訊,空位的上下限是多少,我們絕對可以用python寫幾行就取得結果,然後順便做個資料運算。我們沒有必要很嚴僅地為考慮不同數據的出現情況,我們什至可以hard code - 硬編碼地計算某個Array的元素。直到突然有一天,這個操作變得恆常化,我們還是有條件把之前的python程式碼,改寫成一個規規矩矩的完整腳本,包括異常處理,函數複用。(其實Javascript在改用 NodeJs 作為引擎後,我們還是可以經過 Node.js REPL,來做互動操作,只是Python Shell出現得更早,也是官方支援的功能。) Python這個臨時操作的便利,對於資訊爆炸的年代來講,實在很幫得上忙。再加上現在除了Python Shell以前,還有Jupter Notebook,讓大家可以在Web頁面上,執行像Python Shell的互動操作,對於修過特定區域的程式碼,就更加方便。這些便利,都是不是因為動態語言來創造的優勢,而是實實在在的Coding Anywhere。

Github flow 沒有提及的發佈 - 佈署 | Release - Deployment

科技新知
MacauYeah・2024-08-23

不知道之前為大家介紹的github flow,大家覺得怎樣?好用嗎?今天,筆者又來講講筆者心中認為它沒有好好給出指引的地方。 我們的信心指數,其實沒有那麼高 在前文中,經過 pull request 、 code review 、 auto test ,道理上,開發者可以做的都已經做過了,然後就是等待發佈 - Release。 對於單純的庫類型的程式碼,筆者認為,的確沒有事可以再做,實務上就是直接找人其他程多員試用最新版本,看看有沒有問題。只要 main / master 上,明確的表示版本號的變更,就差不多等於直接發佈。有需要提供binary版本的,就還需要觸發上載binary的流程,但這個跟 pull request 觸發 auto test 差不多, auto test 成功後就上載。 對於服務類型的程式碼,例如 Web App 等,直接發佈到正式環境還是有些不妥吧?始終會即時影響到業務,我們至少有個測試場,經用戶做實際的業務操作去驗收。但這個時機,應該是在Github flow的什麼時候做? 在原始的git flow中,有一個叫做 develop 的相對穩定分支,僅次於 main 。它是功能開發完成後第一次pull request 的地方,我們可以用這個概念來做自動發佈到測試場。但若在github flow 中加入了這個 develop / uat / staging 分支,其實就等於複雜地回到過去傳統的 git flow中,對好多新手來講難以接受。Github flow 的成功簡化,其實很大依賴著自動化測試。現在的測試用例,並不再限於單元測試。就連整合測試,也可以經Docker等容器化技術去做,只要我們的自動化測試有足夠信心,就可以發佈。但反觀我們的 Web App 例子,我們認為自動化測試難似涵蓋所有情境,也難以開發。所以我們還在有個時間發佈到測試場,進行人工測試。 pull request + 快速迭代 筆者結合自己的經驗,配上國外討論區 Stack overflow 的內容,筆者認為Github flow上進行 pull request 後,就是最好的發佈測試場時機。所以我們需要盡快進行驗收測試,完成後在Git commit上加上Tag,以示通過驗收測試,可以發佈正式環境的版本。 不過這個模式是有一個很重要的前題假設:快速迭代。當我們驗收完成後,盡可能快地發佈到正式環境,不然會阻礙下一個功能的pull request驗收,或是覆蓋了上一個pull request的驗收環境。 用反面的例子來說明,如果我們有很多功能需要驗收,或變化很多,或存在多輪的里程碑開發,我們就不適宜那上述模式。最保險的做法,還是回到傳統的 git flow ,引入 develop / uat / staging 分支。但如果大家還是那麼討厭傳統 git flow,筆者還是有另一個提議。 既不想回到傳統 git flow ,但又需要慬㥀的考慮驗收發佈流程 如果開發的功能變化比較大,需要多方面協調、測試、驗收,經歷多次里程碑後,才有一個對外發佈的版本,大家可以考慮分開 Repository 做開發。例如: v1,v2的 Repository 完全獨立。 v1 是已發佈的版本,有獨立的測試場,任何即時候需要修正,就在v1的 Repository 做 pull request。 v2 則是未發佈版本,亦有獨立的測試場。加入任何新功能後,就在v2的 Repository 做 pull request,用自己專用的測試場做驗收。到 v2 正式發佈後, v1 就封存處理,再開一個 v3 作為下一個大版本的開發。這個模式,那怕在庫類型的程式碼也用得上。 這樣做的好處是 git Repository 和歷史記錄都會獨立,自動發佈的腳本程也會簡單明確一些。壞處則是 v1 v2 難以做功能對比,我們只能靠人腦記著 v1 有沒有什麼後期加入的修正和功能,需要同步移植到 v2 中 (相對的,著是同一個Repository,可以利用merge 功能確保 v1 有的,v2 都己處理,只是必需要很懂處理版本衝突問題。

Swarm Mode 上線番外篇:Ceph

科技新知
MacauYeah・2024-08-20

在預設Docker和K8s的容器主導世界裏面,其實一直都缺少了直觀的儲存空間。當你的程序需要讀寫故定的來源資料,該來源就必需是外部的穩定儲存空間,例如是資料庫、NFS。但資料庫、NFS等,要做到真的正穩定,其實就要走Cluster(叢集)模式,確保它們自己本身不是做成single point of failure (單點故障)的元兇。 坊間,只要付得起錢,其實找個穩定的資料庫或NFS,也是有的。但如果你像筆者一樣,只有一塊或多塊【鐵】,就要試試開源的儲存引擎Ceph Storage。 Ceph Storage,有自己特有的CephFS格式,但也支援NFS https://docs.ceph.com/en/quincy/cephadm/install/。也就是,只要我們有足夠多人力,道理上可以自己用實體機去模擬一個穩定的NFS。 因為只是試裝,筆者暫時只用VM來測試,完整的安裝script,可以在這裏找到。script使用Multipass VM,大家有條件的話,可以使用其他VM引擎來看重複。以下是一些官網上沒有提的重點: Ubuntu 24.04 還未能正式使用。在筆者做POC的當是,Ceph v18 在 Ubuntu 24.04上需要先解決,即使大家使用Curl base下載 binary,也未必能成功。 筆者成功測的版本是 Ubuntu 22.04 + Ceph v17,全使用Ubuntu 發佈的內置版本。但大家也要留意自己的Ubuntu apt 有沒有更新到最新版,過去的 cephadm,引用的container image url也變更。記得更新到v17 的最新版,cephadm 指令才能成功取得image。 在官方說明文件的【Deploying a new Ceph cluster】中的【Adding Hosts】https://docs.ceph.com/en/reef/cephadm/install/#adding-hosts 節章可能有些誤導,大家應該要看 【Host Management】中的【Adding Hosts】 https://docs.ceph.com/en/reef/cephadm/host-management/#cephadm-adding-hosts 在每個節點內,可以直觀地連接地Ceph Dashboard,但若大家需要Port Forword,要注意你的Network Interface,筆者就只能經過預設的IPv4的public ip 進行ssh port forward,不能經過0.0.0.0。 Script 位置 https://github.com/macauyeah/ubuntuPackerImage/blob/main/initCephCluster.sh

Spring Data 關聯型態 02

科技新知
MacauYeah・2024-08-09

Presist and Casecade 前次的文章,講了一些Spring Data最基本的關聯概念,但當要正式儲存或刪除,就有些考慮完整性問題。平常我們在處理資料庫的關聯表格時,也需要面Foreign Key的正確性問題。同樣地,Spring Data也有這方面的考量,但它有提份一個很方便的CascadeType選項,可以簡化一些流程。 假設你只能存取Parent Repo,那你需要在Parent中,加入CascadeType.All。當repo.save(parent)時,它就會順多把所有child的也一併進行Save,你也不需要有Child Repo的存在。 @OneToMany(mappedBy="parent", cascade = CascadeType.All) List children = new ArrayList(); 但在複雜的狀況下,例如你不想在更新parent的情況下,不小心弄到child,特別是經過public web下的API操作,你對web client的資料正確性有存疑,就不要使用CascadeType了。這也是筆者認為在大多數情況下,我們都會把Parent和Child的CRUD分開操作,然後根據需要使用各自的repo save。 如果你一定要用CascadeType.ALL (CascadeType.REMOVE),就要再留意刪除的問題。為什麼?因為刪除 parent,其實指的是某個parent不再存在,但不代表child也要一起刪除,child的parent連結可以變為null,也有重新連結其他parent的可能。 如果大家確定需要共同刪除,就可以用CascadeType.ALL 或 CascadeType.REMOVE。 還有一個新的選擇,orphanRemoval = true,也有類似效果。 @OneToMany(mappedBy="parent", cascade = CascadeType.REMOVE) List children = new ArrayList(); // or @OneToMany(mappedBy="parent", orphanRemoval = true) List children = new ArrayList(); // or @OneToMany(mappedBy="parent", cascade = CascadeType.REMOVE, orphanRemoval = true) List children = new ArrayList(); 筆者測試過,混著用也是可以的。若大家看過其他教程,可能會覺得orphanRemoval = true 和 CascadeType 總是一起出現,但它們其實是分別操作的。單獨使用orphanRemoval = true,有時候則是為了不會出現無主的child,但這不代表parent和child的想要同步更新。 JPA Entity 的生命週期 Spring Data跟傳統的資料庫Selete,Create,Update,Delete SQL 語句有所不同。也就是這個不同,它的CascadeType比資料庫的Cascade Update和Cascade Delete更強大。 Spring Data 預設其實是使用 jakarta.persistence.EntityManager,每個Entity主要分為四個狀態 Transient / New - 不在EntityManager的掌控中 Managed - 在EntityManager的掌控中,將會在下次flush時,變成sql create或update statement Detached - 脫離EntityManager的掌控,不受flush影響 Removed - 在EntityManager的掌控中,將會在下次flush時,變成sql delete statement 在Spring Data / Jpa 以前,我們若要直接操作Hibernate,經常見到persist, remove的寫法 entityManager.persist(entity); entityManager.remove(entity); entityManager.detach(entity); entityManager.merge(entity); 其實persist就是把處於Transient、Removed的entity,改為Managed。而remove就是把Managed改為Removed。detach,merge也類似,就是Managed,Detached之間互換。 EntityManager最強大的是,它可以讓程序員不需要再為Managed狀態下的entity操心,它會自動判別下次flush,應該create還是update,如果完全沒有改動的,連update也不會執行。 (註,flush和commit也有不同,flush就是從java寫到資料庫中,在資料庫commit前,還可以使用rollback放棄。) 而Spring Data,則是進一步簡化,它把persist改為save,remove改為delete,然後自動選擇flush的時機。 CascadeType 在解釋完Entity 的生命週期後,終於可以回到CascadeType了。這裏的CascadeType不是資料庫的Cascade操作,其實它是指EntityManager的狀態操作是否有傳遞關係。亦即是,persist(parent)時,要不要連同child也一起操作? 我們查看 CasecadeType 的原始碼,就可以發現可以被傳遞的操作共有以下這些 PERSIST MERGE REMOVE REFRESH DETACH ALL (以上全部) 這裏的 CasecadeType.PERSIST ,跟資料庫的 Cascade Update 是不一樣的。資料庫裏的 Cascade Update,是指當 Parent 的 Primary Key 有變,對應child的 Foreign Key也一起變。但因為 JPA Entity 的機制, Parent 的 Primary Key 不可以改變,理論上不會發生類似資料庫的 Cascade Update,頂多有 Cascade Delete。 CasecadeType.PERSIST 就像之前述的生命週期解說一樣, 把 parent和 child 一起拉到受管理的狀態。 註: CascadeType.REMOVE有點尷尬,似乎有更特別的使用規範。筆者測試過,在某些情況下,CascadeType.REMOVE無法處理ForeignKey問題,又或者是,刪除的順序不對。詳見 spring boot data deletion Reference entity-lifecycle-model spring boot data deletion

Spring Boot 06 - Spring Boot Web 調試工具

科技新知
MacauYeah・2024-08-02

之前兩節,都一直在講怎樣寫code,也介紹了Test Case的好。若為初次接觸,Spring有很多設定需要摸索,若開始時就設定錯誤,對不少人來講都會有很大打擊。在這裏,筆者就介紹一些vscode和spring的工具,可以讓IDE多幫忙一下,減少走歪路的機會。 vscode插件 以下兩個插件,都在於提示用戶設定。 Spring Boot Dashboard (vscjava.vscode-spring-boot-dashboard) 可以那它來運作spring boot app,省去找尋main 位置的麻煩 綜覽整個程式中的所有Bean (Bean是一個很重要的元素,日後會再提及) 若程式為Spring boot web,可以顯示所 http endpoint。 Spring Boot Tools (vmware.vscode-spring-boot) 檢查設定檔的設定值有沒有寫錯 (application*.properties, application*.yml) 綜覽檔案中的有以@為首的與spring相關的元素(檔案很大時就會有用) 可以在IDE運行spring時,查看@元素的bean資訊 (not works ?, 加了actuator也是沒有看見) Spring Initializr(vscjava.vscode-spring-initializr) 經網絡初始化spring 專案的依賴引用設定 Maven for Java (vscjava.vscode-maven) 若大家在使用Spring Initializr時,選取了maven作管理工具,那麼這插件就可以在後續幫忙更新引用。 若專案的Spring 及㡳層引用有變,vscode也需要它來引用更新。 這是java 開發工具包(vscjava)的其中一員,它的其他插件也可以順帶安裝。 調試工具 - open api / swagger-ui 如果我們在開發Web http API ,其實都是為了該某個客戶端使用。但如果該客端明白我們的API該怎樣使用,大家總不會逐個連結,自行編寫使用手冊及範例吧。所以就有了open api 和 swagger-ui 的旦生 。 open api,就是一個公認的使用手冊標準,我們只要在spring-web中加入 springdoc-openapi-starter-webmvc-ui 的程式庫,就可以自動為我們的controller 生成 open api 的說明檔。 更強大的是,這個程式庫可以利用剛生成的open api,配上 swagger-ui ,自動測生一個可供測試的頁面。這個頁面可以供碼農們直接操作,也會產生對應的 curl 指令,讓碼農們可以在任何的主機上重複。這樣,那麼是沒有太多解釋的說明文檔也可以使用。 做法很簡單,在pom.xml中加入依賴。 org.springdoc springdoc-openapi-starter-webmvc-ui 2.5.0 (由於安全性問題,上述程式碼未能完整顯示,請參見文末完成Source Code) 然後我們就可以加入Controller,運行 spring 後,我們可以在 http://localhost:8080/swagger-ui/index.html 找到 swagger 的頁面,然後就可以在 ui 上測試API了。 躲在Proxy背後的 swagger 如果你跟筆者一樣,使用 code-server 或 github codespaces ,你就不能很隨意地連接到 8080 端口。你只能經過Http Proxy去訪問。這樣 open api的原有的設定就不合用了。 這時我們需要自行修改 open api 的 bean,加入我們真正的根路徑。然後筆者使用 code-server,而IDE只會在port 9000上執行,它對外的前置路徑會是 http://localhost:9000/proxy/8080/。 @Bean public OpenAPI springShopOpenAPI() { Server server = new Server(); server.setUrl("http://localhost:9000/proxy/8080/"); return new OpenAPI().servers(List.of(server)); } (由於安全性問題,上述程式碼未能完整顯示,請參見文末完成Source Code) 然後訪問 http://localhost:9000/proxy/8080/swagger-ui/index.html,還會發現 "Failed to load remote configuration." 。但你可以在 "explore" 搜尋欄位內貼上 http://localhost:9000/proxy/8080/v3/api-docs,再一次搜尋檔案,就回復正常了。 註:如果你熟習Nginx這類Reverse Proxy ,你的環境有條件直接修改 Request Header,加入X-Forwarded-*,就不用煩惱寫Bean了,也不用手動在explore裏重新修正api-docs的位置。詳見 https://springdoc.org/index.html#how-can-i-deploy-springdoc-openapi-starter-webmvc-ui-behind-a-reverse-proxy Controller的繼承 Spring Controller的 @ 標記 (Annotation) ,其實支援繼承的。經Spring 生成的 api docs,也有如何效果。例如以下程式碼 public class ParentController { @GetMapping("/postfix") public String postfix(){ return "this is postfix"; } } @RestController @RequestMapping("/api") public class ChildController extends ParentController { @GetMapping("/direct") public String directCall() { return "direct result"; } } (由於安全性問題,上述程式碼未能完整顯示,請參見文末完成Source Code) 在ChildController的實例中,它會有兩個API,分別是 /api/direct /api/prefix 它支援Java Function Overwrite(覆寫),但不能改 @ 標記,以下就是一個錯的例子 @RestController @RequestMapping("/api") public class ChildController extends ParentController { @GetMapping("/Overwrite") // 把這個 @ 行刪了才能正常執行 public String postfix(){ return "this is Overwrite"; } }(由於安全性問題,上述程式碼未能完整顯示,請參見文末完成Source Code) Source Code spring boot web api doc

Swarm mode 上線 4 | IP 設定

科技新知
MacauYeah・2024-07-23

單機模式 IP設定 平常我們自己做測試,網絡功能通常用預設的就好。但當我們的Docker Container需要存取在區域網內的其他資源,避晚IP網段相衝是必需要的事。 大部份情況下,單機Docker使用的預設IP段會是 172.17.0.0/16 172.18.0.0/16 ... 若然現在區域網中,有一段172.18.0.0/24,大家不想Docker踩到其中,可以修改設定檔,加入預設的default-address-pools,以後它就只會從指定的區段使用。 # vim /etc/docker/daemon.json { "default-address-pools": [ { "base": "172.17.0.0/16", "size": 24 }, { "base": "172.19.0.0/16", "size": 24 }, { "base": "172.20.0.0/16", "size": 24 } ] } 其中base,是docker可以操作的總區域,size指的是Docker要自行分段的話,每段的大小是多少,上述的例子,就代表未來可能有以下Docker 網段。 172.17.0.0/24 172.17.1.0/24 ... 172.17.255.0/24 172.19.0.0/24 172.19.1.0/24 ... 172.19.255.0/24 172.20.0.0/24 172.20.1.0/24 ... 172.20.255.0/24 修改完設定後,重啟Docker就會生效。當然,重啟前,先刪除所有不在預設範圍的所有Container。 Swarm模式 IP設定 Swarm模式,與單機差不多,它需要在初始化Swarm就要定義,而且它不能與單機的網段有重疊。單機會預設使用Private IPv4 Class B,Swarm則是預設使用Private IPv4 Class A段,所以我們若就更改,就使用10.x.x.x吧。 docker swarm init --default-addr-pool 10.1.0.0/16 --default-addr-pool-mask-length 24 經上述例子初始化的 ingress 網段,將會是 10.1.0.0/24,隨後每個stack 則會是 10.1.1.0/24 10.1.2.0/24 10.1.3.0/24 重置Swarm 跟單機的情況類似,如果已建立Swarm後才修改網段,還是要整個刪掉重來。 每個節點都要執行以下指令。 docker swarm leave --force 實測swarm leave這個指令也會把所有運行中的stack刪掉。 各節點重新建立swarm # in node 1, init new swarm with new ip docker swarm init --default-addr-pool 10.1.0.0/16 --default-addr-pool-mask-length 24 # in node 1, get new manager token docker swarm join-token manager # in node 2 and node 3, join node 1 with new token docker swarm join --token XXXXX YOUR_NEW_NODE1_IP:2377 雙管齊下 如果大家同想要修定單機及Swarm的網段,還要留意有一個特別的網段docker_gwbridge。它雖然是Swarm的附帶產物,但它則是受單機的網段控制。也就是,如果大家有需要同時修改單機及Swarm的網段,則需要手動刪除Swarm及docker_gwbridge 在每個節點先刪掉舊有的Swarm及docker_gwbridge,並關掉docker docker swarm leave --force docker network rm docker_gwbridge 在每個節點為docker_gwbridge修改設定,然後重起docker # vim /etc/docker/daemon.json { "default-address-pools": [ { "base": "172.17.0.0/16", "size": 24 } ] } 然後像前述一樣,重起Swarm。

【James Altucher的Unilateral Pairs Trading 策略- 5年回報627.75%】

創富坊
程式交易 www.quants.hk (導師: 財經書藉作家: 麥振威)・2024-07-22

在金融市場中有一個人物頗具爭議性,他曾經身家由逾千萬美元跌至一無所有,其後又輾轉變得富有。他便是James Altucher,現在大家基本上經常看到他演講的內容都是與個人成長及心靈有關。 James Altucher試過銀行戶口只剩下143美元,但其後又把身家翻至1500萬美元,要說心靈的故事他自然有很多東西可以發表。但他除了創業做生意外,由於曾在多家對沖基金工作,所以一直都有投資股票及加密貨幣。 對他有興趣的讀者也可以留意他的blog: https://jamesaltucher.com/blog/ (圖一) 他blog內的內容有些其實也有參考價值,例如他寫過一篇題目為《THE PERFECT INVESTMENT STRATEGY》的文章,他會說自己本質上是一個非常簡單的人,並不真的喜歡投資,只喜歡學習,喜歡遊戲,喜歡看電視,寫作,做播客等等,還有非常喜歡睡覺。他認為完美的交易策略就是在生活中找到最具潛力的領域,然後買入這個行業中全部的股票。 例如你在1970年到1990年間看好電腦行業,然後你投資每一家即將要上市的公司,假設你買入了合共100家電腦公司股份,每家用1,000美元去買,那你總共投資了10萬美元。但這100家公司中有98家公司最後都破產,不過這並不重要,因為存活下來的2家公司能把你的資產翻至350萬美元。若超過兩家公司能存活,你能賺取的利潤會更多。 除了blog外,他還寫過兩本書,分別是《Trade Like a Hedge Fund》及《Choose Yourself!》。(圖二) 《Trade Like a Hedge Fund》這本書在2004年已出版,筆者就頗為喜歡,若中文版的名稱應該較多人聽過,中文譯名為《20招成功交易策略》,書中他提及的分析方法其實很值得參考。首先他認為交易策略應該簡單的策略才是交易中最穩鍵的。但所謂簡單的策略,又不是像Larry Connors那種初級班的策略。 可以說James Altucher的策略是由複雜的策略進行簡化,目的就是提高真實交易時的執行加,這與那些RSI(2)超賣再超賣的策略並不相同。 James Altucher在《Trade Like a Hedge Fund》中曾經提及一套名為「Unilateral Pairs Trading」的策略便很值得參考,筆者研究Pair Trade的方法已經很久,而James Altucher也在書中道出了Pair Trade的關鍵,他認為Pair Trade雖然對市場的方向是中立的,意思是你沒有估市況升/跌,但實際上對兩個產品的差價是有偏見的,做Pair Trade的人是在估計差價會擴大還是縮小,所以也會要去估,而非完全沒有任何預測就能賺錢。 但Pair Trade的問題是,炒家同時運用兩個「工具」來做交易,在真實交易時當兩個工具的價格也變得不尋常之時,炒家就不只面臨一個資產的風險,要處理的事情就會更多,而且也存在兩個資產同時虧損的可能性。(圖三) 不過,運用Pair Trade的人都是十分擅長去估計兩個工具之間的差價,有些人擅長預測股價,有些人則會認為預測兩個工具的差價變動會較容易。不過,差價的波動會較股價為少,而且若市場越來越多的人在做Pair Trade,差價會變得更少,因此炒家若要追求更高的回報,就需要利用槓桿,但風險也會因而提升。 所以James Altucher認為,其實可以進行單邊對沖交易,那就是雖然觀察兩個資產的價格差距來做交易,但最終只會買入或沽空其中一個資產,他認為這樣做其實更好,因為其中一個資產的價格變得很不合理時,炒家會預測價格會回歸正常值,假設兩個資產中更為波動的一個資產偏高時便直接沽空,偏低時便直接買入,根本不用兩個資產同時交易,最終也是能達到預測價差收窄的結果,但進行單邊對沖交易就更加有靈活性,而且風險相對較低。 但「Unilateral Pairs Trading」不只適合交易正股,若用以交易流動性更大的ETF如QQQ及SPY等,James Altucher認為效果會更佳。筆者則把相關策略修改,再用SQQQ的數據作測試,結果也證實不俗。下一篇文章會告訴大家 James Altucher所研究的「Unilateral Pairs Trading」詳細內容。 (來看Patreon文章) 筆者Patreon: https://www.patreon.com/quantshk 網頁:www.quants.hk

將583.15元翻至1000萬的Ross Cameron 用了什麼交易策略? (一)

創富坊
程式交易 www.quants.hk (導師: 財經書藉作家: 麥振威)・2024-07-16

在Youtube上大家經常看到很多教授交易策略的外國炒家,如2016年曾贏得「The Million Dollar Trader Competition」的Nial Fuller、聲稱將583.15元翻至1000萬的Ross Cameron,還有TradingMarkets.com創辦人Larry Connors等。 之前已介紹過Larry Connors的R3 Trading Strategy,今天想跟大家討論有關Ross Cameron的事跡及他的交易策略。 Ross Cameron的影片相信很多讀者都在Youtube看過,看他的樣子就看不出已經58歲,若稱它為Daytrade大師應該大家也很同意,他的Youtube名稱就稱為「DaytradeWarrior」,中文就是「日內交易戰士」。 https://www.youtube.com/@DaytradeWarrior Ross Cameron曾經透過Daytrade將約400萬翻至1000萬。而且他出售的一套交易系統,大約有超過2萬人各用了數千美元購買,不過後來就被聯邦貿易委員會指他的公司通過虛假和不切實際的承諾銷售系統,而購買的客戶大多數也沒有任何投資上的回報。 筆者沒有買過他的系統,也絕不建議大家去買,他的影片提及很多的交易技巧其實也只是「老生常談」,首先他認為Daytrade是最有利可圖的交易類型,因為即市開倉及平倉就避免了持倉過夜出現重大虧損的機會。但他強調Daytrade也必需有良好的風險管理,你要賺得更多,自然就需要冒更大的風險,所以在有限風險下不可能期望市場會每天給你很驚人的回報,甚至有很多日子根本是沒有回報的。 另外他強調,若要做Daytrade,本金至少要有25000美元,大約是195000港元。因為市場是一個很「嚴格」的領域,而且Daytrade不可能每天都賺錢,若本金根本不足,可能很也便會輸光離場。 雖然他主力是做「low float stock」,不過他提出的交易策略也有一些是值得參考的,有些準則也適合應用在一些熱門股之上。 1)交易中的3-5-7規則: 先要計算價格持續上漲或下跌的天數、若用小時圖則看有多少個小時,若用5分鐘圖則看有多少個5分鐘,然後大家會發現,在第三、第五或第七根陰陽燭上,都會是相反方向出現的時間。 筆者就覺得若應用在Daytrade上,例如觀察5分鐘圖表,連續3根陰陽燭的價格都在下跌是經常出現的情況,故此未必有參考價值,而連續5根陰陽燭的價格也在下跌,這種情況雖較少,但也不一定會出現反彈,但若連續7根陰陽燭的價格都在下跌,基本上很少出現,但若出現時,價格確實很大機會反彈。 如(圖一)是Tesla(US:TSLA)的5分鐘圖,2023年12月14日當日便出現這種情況: 2) 3天法則 由於每個投資者都必須在三個工作日內結算他們的證券交易。他的意思是用現金戶口,這個結算週期被稱為「T + 3」,若用孖展戶口則可以「T+0」。而現金戶口的「T+3」規則意味著當投資者購入股票後,證券交易商必須在交易執行後的三個工作日內收到投資者的付款。但若投資者未能付款就必需賣出股份,故此股市中若連續上升三天後都大多會調整,又或者出現升勢放緩。 但筆者就認為,這個3天法則在「弱市」中才較多出現,在市況十分強的情況,3天法則並不適用。 如2022年與2023年便有很大的分別,2022年屬於「弱市」,2023年則屬於「強市」,3天法則在2022年就經常出現。 例子: (圖二) Apple(US:AAPL)的日線圖上,2022年經常會看到上升3天後便升勢放緩的情況: 但同樣看Apple的日線圖,在2023年裏3天法則並不適用: (圖三) 除了以上的兩個法則,Ross Cameron也講解過如何去選股,以及何時應該入市,他稱之為「momentum-day-trading-strategy」。 這套交易策略每天只會交易兩個小時,但交易前卻要有很多的準備,首先就是要找出具備「動能」的股票,要透過Daytrade實現利潤,Ross Cameron認為選股的過程十分重要,一些具備「動能」的股票甚至可以一天內上升20%至30%。但這些股票幾乎每天都有的,只是大家能否找到它們。 Patreon 的文章有介紹他的momentum-day-trading-strategy,以及他的交易策略若用Trading View寫出來後的backtest結果如何。(來自Patreon文章) 筆者Patreon: https://www.patreon.com/quantshk