Total Pageviews

2019/04/05

[Spring boot] How To Do @Async in Spring

Setup Asynchronous configuration:
package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
// enable asynchronous processing with Java configuration
@EnableAsync
public class AsyncConfig {

    @Bean("githubUserLookupExecutor")
    public ThreadPoolTaskExecutor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(1000);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("Async-");
        return executor;
    }

}



Create a GitHub Lookup Service:
package com.example.service;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.concurrent.CompletableFuture;

/**
 * GitHub Lookup Service
 */
@Slf4j
@Service
public class GitHubLookupService {

    @Value("${http.proxy.host}")
    private String host;

    @Value("${http.proxy.port}")
    private Integer port;

    /**
     * The method needs to be public so that it can be proxied.
     * And self-invocation doesn’t work because it bypasses the proxy and
     * calls the underlying method directly
     *
     * @param name user name
     * @return
     */
    @Async("githubUserLookupExecutor")
    public CompletableFuture<User> findUser(String name) {
        log.debug("looking up {}", name);

        String url = String.format("https://api.github.com/users/%s", name);
        User user = new RestTemplate(setupProxy()).getForObject(url, User.class);

        return CompletableFuture.completedFuture(user);
    }

    private SimpleClientHttpRequestFactory setupProxy() {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port));
        requestFactory.setProxy(proxy);
        return requestFactory;
    }


    /**
     * Representation of a GitHub User (JSON to Object)
     */
    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class User {
        private String login;
        private String name;
        private String blog;
        private String location;
    }

}



Test code:
package com.example.test;

import com.example.service.GitHubLookupService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import java.util.concurrent.CompletableFuture;

@SpringBootApplication
@ComponentScan(basePackages = "com.example")
@Slf4j
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    @Bean
    CommandLineRunner run(GitHubLookupService service) {
        return args -> {
            // Kick off multiple asynchronous lookups
            CompletableFuture<GitHubLookupService.User> junyuo = service.findUser("junyuo");
            CompletableFuture<GitHubLookupService.User> springProjects = service.findUser("Spring-Projects");
            CompletableFuture<GitHubLookupService.User> tensorflow = service.findUser("tensorflow");
            CompletableFuture<GitHubLookupService.User> dotnet = service.findUser("dotnet");
            CompletableFuture<GitHubLookupService.User> google = service.findUser("google");

            // Wait until they are all done
            CompletableFuture.allOf(junyuo, springProjects, tensorflow, dotnet, google).join();

            log.debug("user = {}", junyuo.get());
            log.debug("user = {}", dotnet.get());
            log.debug("user = {}", springProjects.get());
            log.debug("user = {}", google.get());
            log.debug("user = {}", tensorflow.get());
        };
    }

}


Console log:
2018-12-06 11:01:52.358  INFO 11440 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-12-06 11:01:52.361  INFO 11440 --- [           main] com.example.test.TestApplication         : Started TestApplication in 2.522 seconds (JVM running for 3.465)
2018-12-06 11:01:52.370 DEBUG 11440 --- [        Async-3] com.example.service.GitHubLookupService  : looking up tensorflow
2018-12-06 11:01:52.370 DEBUG 11440 --- [        Async-4] com.example.service.GitHubLookupService  : looking up dotnet
2018-12-06 11:01:52.370 DEBUG 11440 --- [        Async-5] com.example.service.GitHubLookupService  : looking up google
2018-12-06 11:01:52.370 DEBUG 11440 --- [        Async-2] com.example.service.GitHubLookupService  : looking up Spring-Projects
2018-12-06 11:01:52.370 DEBUG 11440 --- [        Async-1] com.example.service.GitHubLookupService  : looking up junyuo
2018-12-06 11:01:53.759 DEBUG 11440 --- [           main] com.example.test.TestApplication         : user = GitHubLookupService.User(login=junyuo, name=Albert Kuo, blog=http://albert-kuo.blogspot.com/, location=Taipei)
2018-12-06 11:01:53.759 DEBUG 11440 --- [           main] com.example.test.TestApplication         : user = GitHubLookupService.User(login=dotnet, name=.NET Foundation, blog=http://www.dotnetfoundation.org, location=null)
2018-12-06 11:01:53.759 DEBUG 11440 --- [           main] com.example.test.TestApplication         : user = GitHubLookupService.User(login=spring-projects, name=Spring, blog=http://spring.io/projects, location=null)
2018-12-06 11:01:53.759 DEBUG 11440 --- [           main] com.example.test.TestApplication         : user = GitHubLookupService.User(login=google, name=Google, blog=https://opensource.google.com/, location=null)
2018-12-06 11:01:53.759 DEBUG 11440 --- [           main] com.example.test.TestApplication         : user = GitHubLookupService.User(login=tensorflow, name=null, blog=http://www.tensorflow.org, location=null)



2019/04/04

[閱讀筆記] 人類大命運 (2/8)


  1. 閱讀歷史最好的理由,不是為了預測未來,而是要將自已從過去中解放,想像是否有另一種命運。當然,我們仍不免受到過去的形塑,所以永遠不可能得到完全的自由;然而,部分的自由總是比全無自由,來得強多了。(p.75)
  2. 在我們想要把自己變成神的這時刻,回頭看看自己的起源,更加倍重要。要討論人類化身為神的未來之前,不能不談人類身為動物的過去、以及人類與其他動物的關係;原因在於,人類與動物之間的關係如和,很有可能就是未來超人類和人類之間關係的模樣。想知道超級聰明的半機械人,可能怎麼對待只是一般血肉之軀的人類嗎?先去看看人類如何對待比較不聰明的動物表兄弟吧。當然,這絕對不是完美的類推,但這是我們唯一能夠觀察、而不只是想像的最佳原型。(p.77)
  3. 人之所以害怕改變,是因為害怕未知。但是,歷史最不變的事實,就是一切都會改變史上早已見證許多宗教、帝國和文化的起落,這樣的起伏動盪並不一定是壞事。(p.78)
  4. 豢養動物從古至今的生活狀況,都受到兩個因素互相拉扯:人類的欲望、動物的需求。人類養豬,是為了得到豬肉;如果希望豬肉供應穩定,就必須確保豬能夠永續生存繁衍。照道理說,家畜應該能夠因此避開各種極端的殘酷對待。如果農夫不照顧好自己的豬,讓豬還沒生小豬就死了,這下就會輪到農夫餓死。但不幸的是,人類卻有各種方式給家畜帶來無盡苦難,但同時又能確保家畜永續生存繁衍。這個問題根源在於:家畜仍然繼承野生動物的種種生理、情感和社交需求,但這對人類的農場來說毫無意義。農夫常無視這些需求,而且不會因此在經濟上付出任何代價。動物被鎖在狹小的籠子裡、母幼骨肉分離等,這些動物飽受痛苦,但仍然繼續生存繁衍。農業革命讓人類有了確保家畜生存繁衍的能力,卻忽略了家畜的主觀需求(p.91)
  5. 整部人類歷史的農夫,雖然提供小豬、小牛物質上的需求,卻往往忽略牠們的情感需求。於是,不論是養豬場或是酪農業,都是以打斷哺乳動物最根本的情感連結作為基礎。農民讓母豬和母牛不斷懷胎,但小豬和小牛卻是出生沒多久,就被迫與母親分離,常常終其一生都未能祇到母親的眼淚、也沒能感受到它的舌頭和身體的溫暖。(p.102)
  6. 為什麼現代人如此熱愛甜食?可不是因為到了 21 世紀初,我們還得大吞冰淇淋與巧克力,才能生存下去。反而是因為,我們石器時代的祖先由於常遇到食物短缺,如果碰到香甜的水果或蜂蜜,最明智的做法就是盡量吃,越快越多越好。(p.92)
  7. 年輕人為什麼開車魯莽、吵架衝動、還愛駭進機密網站?因為他們還是照著遠古基因的指令行事。執行這些指令,在今天不僅無用,可能還有反效果,但在七萬年前,可是深深切合演化的目的。當時,年輕的獵人如果冒著生命危險追趕猛瑪象,就可能勝過所有競爭對手,贏得當地美女的芳心;而我們現在就是還擁有這種男子氣概的基因。(p.92)
  8. 演化就是變化,而且無法產生永恆的實體。從演化角度來看,我們最接近人類本質的就是我們的 DNA,但 DNA 承載的絕非永恆,而是突變。(p.119)
  9. 主觀經驗有兩個基本特徵:感覺與欲望之所以說機器人和電腦沒有意識,是因為它們能力強大,卻沒有什麼感覺,也沒有什麼欲望。機器人可能有電量感測器,在電池快沒電時,向中央處理器發出訊號,讓機器人移向插座、自己插上插座充電。但是在整個過程中,機器人不會有什麼感覺;相對的,快要耗盡能量的人,會感覺饑餓,一心渴望能停止這種不愉快的感覺。正因為如此,我們才會說;人類是有意識的生物,而機器人則否。逼人工作到過度飢餓和疲憊而崩潰是一種罪,然而讓機器人工作到電池耗盡,卻沒有任何道德問題(p.120) 
  10. 大腦是相當複雜的系統,有超過八百億個神經元互相連結,組成無數細密的網路。而在幾十億的神經元來回送出幾十億個電訊號時,主觀經驗就此浮現。雖然電訊號的傳送和接收,只是很簡單的生化現象,但這些訊號的互動卻會創造出複雜的東西:意識流 (stream of consciousness)。我們在許多其他領域,也能觀察到同樣的動態。譬如,單一車輛的移動只是簡單的動作,但幾百萬輛同時移動及互動,就出現了交通阻塞。單一股票的買賣再簡單不過,但幾百萬股民同時買賣著幾百萬張股票,就可能造成讓專家跌破眼鏡的經濟危機(p.123)
  11. 有些科學家認為,意識沒有任何生物學上的功用。也就是說,意識是大腦某些程序製造出來的副產品,沒有生物學上的用途,就像是飛機的噴射引擎會發出隆隆巨響,但噪音並不會推動飛機前進。又好像人類並不需要二氧化碳,但是每次呼吸都讓空氣多了二氧化碳。同樣的,意識可能就是「在複雜的神經網路訊號傳送之後,造成的心理污染」,沒有任何功用,就是存在那裡。這絕對是個值得思考的想法,雖然可能並不正確,但這也讓我們很驚訝地發現,當代科學在今日要解釋意識,這竟然已經是最佳的理論。(p.132)
  12. 圖靈測試 (turing test) 認為,想判斷某台電腦算不算具備心靈,做法是安排測試者同時和電腦及另一個真人溝通,而測試者不知道哪個是電腦、哪個是真人。測試者可以任意問問題、玩遊戲、辯論、甚至是調情,時間長短不限;然後再來判斷哪個是電腦、哪個是真人。如果測試者無法決定或根本選錯,就等於電腦通過了圖靈測試。(p.135)
  13. 在本質上,我們人類和大鼠、狗、海豚或黑猩猩,並沒有多大的差異之處。正如牠們,我們也沒有靈魂;也正如我們,牠們也有意識,有著充滿感覺和情感的複雜世界。當然,每隻動物都有自己獨特的特質與才能,而每個人也有自己獨特的天賦。不過,我們倒也沒有必要進一步會動物都強加人性,覺得他們就像是長了毛的人類。這種畫蛇添足的做法,不僅在科學上無法立足,也讓我們無法真正從動物的立場,給予牠們理解和評價。(p.144)
  14. 如今人類完全主宰地球,並不是因為單一人類比單一黑猩猩或狼更聰明、或是手指更靈巧,而是地球上只有智人這個物種,能夠大規模而靈巧的合作。智力和工具製造當然非常重要,但如果人類還沒學會如何大規模靈活合作,即使大腦再聰明、手指再靈巧,現在仍然是在敲燧石,而不是撞擊鈾原子。儘管其他物種也有合作的能力,但是只有智人能與無數陌生個體,進行非常靈巧的合作。正是這種實際具體的能力,說明了為何目前是由人類主控地球,而不是什麼永恆的靈魂、或是獨有的意識。(p.148)
  15. 歷史已經提供充分證據,點出大規模合作極端重要。勝利幾乎永遠屬於合作更順暢的一方;這不只適用於人與動物的爭鬥,也適用於人群與人群之間的衝突。羅馬之所以征服希臘,不是因為羅馬人的腦子比較大、或工具製造技術比較高明,而是因為他們的合作更具效率和效益。綜觀歷史,紀律嚴明的軍隊就是能擊敗散兵游勇,團結的菁英就是能凌駕烏合之眾(p.149)
  16. 想掀起一場革命,光靠人數,絕對遠遠不夠。革命靠的通常是小群人集成的網路,而不是一大群人的動作。如果你想發動一場革命,不要問「有多少人會支持我的想法?」而是要問「我有多少支持者能夠有效合作?」俄國 1917 年爆發十月革名,引爆點並不是一億八千萬農民起身反抗沙皇,而是一小群共產主義信徒在對的時間,站到對的位置。(p.149)
  17. 研究指出,不管是友好或敵對的關係,智人能真正熟識的對象不超過 150 人。不管人類是靠什麼打造出大規模合作網路,總之絕不只是彼此熟識而已。(p.156)
  18. 行為經濟學上最著名的「最後通牒賽局 (ultimatum game,又稱承讓賽局)」,不僅戳破古典經濟學理論,也建立起近幾十年最重要的一項經濟發現:智人的行事並不是依照冷冰冰的數學邏輯,而是根據有溫度的社交邏輯。我們會拒絕不公平的方案,這是因為如果在石器時代,溫和接受一切要求,就只是等死(p.157)
  19. 「像天神獻上十頭牛,就會下雨;孝順父母,就會上天堂;如果不相信我說的話,你就會下地獄。」只要智人住在相信同樣一套故事的地方,就會遵守一樣的規矩,不僅很容易預測陌生人會有什麼行為,也很方便組織大規模的網路。智人也常常用可見的標記(例如頭巾、鬍子或西裝)來代表「你能相信我,我跟你信仰的故事是一樣的」。但我們那些黑猩猩堂兄弟,並無法創造和流傳這樣的故事,也因此無法大規模合作(p.160)
  20. 現實分成三種 (p.160~161)
    1. 客觀現實:指事物的存在與我們的信念和感受無關,例如重力就是一項客觀現實,早在牛頓發現之前便已存在,而且不管信不信它,都同樣會受到重力影響。
    2. 主觀現實:事物存在與否,取決於個人的信念和感受。例如假設我覺得頭一陣劇痛去看醫生,雖然醫生對於頭部做了徹底檢查,卻查不出問題,又去做了血液、尿液、X 光、fMRI、心電圖,什麼都做了.等到檢查結果出爐,醫生說我完全健康,可以回家了,可是我仍然覺得頭痛。雖然客觀測試都找不出我有什麼問題,儘管除了我以外沒有人感覺痛苦,但對我來說,這種痛苦是 100% 真實的。
    3. 互為主體 (intersubjective) 的現實:並不是因為個人的信念或感受而存在,而是靠著許多的溝通而存在。歷史上有許多最重要的驅動因素,都具有互為主體的概念。像是金錢,並沒有客觀的價值,1 元美鈔不能吃、不能喝,但只要有幾十億人都相信它的價值,你就可以拿來買東西吃、買飲料喝、買衣服穿。

2019/04/03

[閱讀筆記] 人類大歷史 (4/6)


  1. 歷史的鐵則就是:事後看起來無可避免的事,在當時看起來總是毫不明顯。直到今天,情況仍就如此。我們已經走出全球經濟危機了嗎?還是前面有更大的打擊?中國會不會繼續成長、成為全球第一個超級大國?美國會不會喪失霸主地位?以上所有走向,評論家都各自有一套很完整的論述,但是我們就是無法確定何者為真。但如果過了數十年後再回顧,我們就會覺得答案真是太明顯了。但是真正最知道當時情況的人 (也就是活在當時的人類),正是最看不出歷史走向的人。(p.269)
  2. 混沌系統 (chaotic system) 分成兩種 (p.271)
    1. 一階混沌:指「不會因為預測而改變」,例如天氣就屬於一階混沌系統。雖然天氣受到無數因子影響,但是我們可以建立電腦計算模型,不斷加入越來越多因子,讓天氣預報越來越正確
    2. 二階混沌:指「會受到預測的影響而改變」,因此永遠無法準確預測
      1. 市場就屬於二階混沌系統。假設我們開發一套電腦程式,可以完全準確預測明天的油價,情況會如何?可以想見,油價會立刻回應這個預測而波動,最後也就不可能符合預測。
      2. 政治也屬於二階混沌系統。很多人批評研究蘇聯的學者沒能預測到 1989 年的革命,也嘲笑中東專家沒有料到 2011 年會爆發阿拉伯之春革命。但這是不公平的,從定義上,革命就是無法預測,如果真能預測有革命,革命就永遠不會成真
  3. 歷史不像是物理學或經濟學,目的不在於做出準確預測。我們之所以研究歷史,不是為了要推知未來,而是要拓展視野,要瞭解現在的種種絕非「自然」,也並非無可必免,未來的可能性遠超過我們的想像。舉例來說,研究歐洲人究竟是如何控制非洲人,我們就知道種族歧視絕非自然或無可避免,而且知道世界大有可能是完全不同的樣貌。(p.272)
  4. 雖然我們無法解釋歷史做出的選擇,但有一點可以確定:歷史的選擇絕對不是為了人類的利益。隨著歷史眼鏡,毫無證據顯示人類的福祉必然提升。沒有任何證據,證明對人類有益的文化就會成功擴張,而對人類無情的文化就會消失。沒有任何證據,證明基督教是比摩尼教更好的選擇,或證明阿拉伯帝國比波斯帝國對人類更有力。沒有任何證據,證明歷史是為了人類的利益而進展;原因就在於「利益」並沒有客觀的衡量標準。不同的文化對於「善」的定義不同,而且並沒有客觀標準可以決定何者為佳。(p.272)
  5. 很多時候,各國的軍備競賽只會拖垮所有彼此對立的國家,並不會真正改變軍事力量的平衡。巴基斯坦買了先進戰機,印度就會立即跟進;印度發展核彈,巴基斯坦也有樣學樣;巴基斯坦擴編海軍,印度立刻訪像。在這一切過程結束的時候,雙方權力平衡很可能根本和過去沒有什麼改變,但原本可用於教育或醫療的數十億美元經費,就這樣浪費在武器上。然而,這種軍備競賽的發展,難以抗拒。軍備競賽就是一種行為模式,像是病毒一樣,從一個國家傳到另外一個國家,傷害了所有人,只對行為模式本身有利,符合演化論上繁衍、複製的要求(p.274)
  6. 軍備競賽就像「自私的基因」一樣,本身並沒有意識,並不是自覺地在尋求生存和繁殖,其傳播是在難以阻擋的發展下,一個意外的結果(p.274)
  7. 無論我們把歷史發展的動力稱為「賽局理論」、「後現代主義」或「瀰因學」,「提升人類福祉」絕對不是主要目標。並沒有證據顯示,史上最成功的文化就一定是對智人最好的文化。而就像演化一樣,歷史的演進並不在意生物個體是否幸福。至於對個別人類來說,即使受到了歷史演進的影響,但通常一方面太過無知、一方面又太過軟弱,因此無力改變。(p.275)
  8. 科學革命的回饋循環。科學需要的不只是研究本身要有進展,更需要科學、政治與經濟彼此相互強化。如果沒有政治和經濟組織提供資源,科學研究幾乎就不可能成功。反過來說,科學研究也為贊助者帶來新的能力,讓他們能夠取得新的資源,而部分資源就會用來研究新的能力。以美國政府為例,最近數十年投入數十億美元從事核物理研究。靠著相關研究,美國得以興建核電廠,為美國產業提供廉價電力,而產業又能繳稅給美國政府,政府在提供一部分經費,繼續核物理研究。(p.280) 

  9. 現代科學與先前的知識體系有三大不同之處:(p.281)
    1. 願意承認自己的無知:承認自己並非無所不知,更重要的是,我們也願意在知識進展之後,承認過去相信的可能是錯的。於是,再也沒有什麼概念、想法或理論,是神聖不能挑戰的。
    2. 以觀測和數學為中心:透過搜集各種觀測數據,在用數學工具整理分析,形成理論。
    3. 取得新能力:光是創造理論還不夠,現代科學還希望能夠運用這些理論來取得新的能力,特別是發展出新技術。
  10. 科學革命並不是「知識的革命」,而是「無知的革命」。真正讓科學革命起步的偉大發現,就是發現「人類對於最重要的問題其實毫無所知」。(p.281)
  11. 現代科學是一門獨特的知識體系,獨特之處就在於公開承認這「整套體系」都對於一些「最重要的問題」一無所知。達爾文從來沒說過自己是「生物學家的封印」、說自己已經完全解開生命謎團。經過幾個世紀的大規模研究,生物學家承認,他們還是無法完整解釋為什麼大腦能產生意識。物理學家也承認,他們不知道是什麼引起宇宙大霹靂,也不知道如何讓量子力學與廣義相對論統合起來。(p.283)
  12. 有些時候,因為不斷有新證據出現,各種科學理論也就互相交鋒、戰火熱烈.一個典型的例子,就是究竟哪一種計量經濟模型最好。雖然每個計量經濟學家都會說自己的模型最恰當,但是每次出現金融危機和股市泡沫,我們就會看到主流改變;目前一般公認,我們還是不知道最佳的計量經濟模型究竟為何。雖然我們一般認定主流理論為真,但每個人也都同意,如果新證據出現而與主流理論相違背時,主流理論也就需要修正、甚至是淘汰(p.283)
  13. 現代科學沒有需要嚴格遵守的教條,但研究方法有一個共同核心:搜集各種實驗觀測資料,並以數學工具整理。主流的現代研究方法會預設舊知識有所不足,而且這時候的重點不在於研究舊的知識體系,而是要強調新的觀測、進行新的實驗。如果觀測到的現象與過去的傳統知識體系相衝突,我們會認為現在的觀測結果才是正確的(p.285)
  14. 綜觀歷史,社會上有兩種貧窮:第一、社會性的貧窮,指的是某些人掌握了機會,卻不願意釋出給其他人;第二、生物性的貧窮,指的是因為缺乏食物和住所,使人的生存受到威脅。或許社會性的貧窮永遠都會存在,無法根除,但在全球許多國家,生物性的貧窮已成過去式。許多社會現在的問題是營養過剩,胖死比餓死的機率更高。(p.296~297)
  15. 科學研究之所以能得到經費,多半是這些研究有助於達到某些政治、經濟或宗教目的。1940 年代,美國與蘇俄投入大量資金研究核物理,而不是水下考古。根據他們推測,研究核物理有助於發展核武,而水下考古對於贏得戰爭,沒什麼幫助。科學家本身並不一定會察覺到各種金錢流動的政治、經濟和宗教利益;許多科學家確實只是純粹為了求知而研究。然而,真正控制科學發展進度表的,很少是科學家(p.304)
  16. 雖然歐洲、中國和穆斯林世界在 1750 年看起來,沒什麼差異,但這其實只是假象。這就像是有兩家建商同時開始興建高樓,一家使用的是木材和泥磚,另一家使用鋼筋和混泥土。一開始,兩個工地無論興建速度或建築高度,都相去無幾,看起來這兩種建築工法也就沒什麼高下之分。但等到一過了某個樓層,木材和泥磚蓋的高樓再也無力支撐,於是頹然傾塌,而鋼筋混泥土蓋的高樓卻還是屹立不搖,甚至繼續向上伸展到人類目光的極限。(p.314)
  17. 雖然科技在 19 世紀和 20 世紀大放異彩,但在近代的早期並不突出。這裡的真正關鍵因素在於,不管是想尋找植物的植物學家,或是想尋找殖民地的海軍軍官,都有一種共同的心態。他們共同的出發點就是承認無知,都會說「我不知道那裡有什麼」。於是他們都很好奇,都覺得有走出去、尋找新發現的必要;而且他們都希望這樣取得新知識,能夠讓他們成為世界的主人。(p.316)
  18. 歐洲帝國主義和先前所有帝國完全不同。過去的帝國主義者,都認為自己已經了解整個世界,「征服世界」只是為了要利用和傳播他們自己對於世界的看法,擴張自己的權力和財富。以阿拉伯人為例,他們征服埃及、西班牙和印度,並不是為了想找出什麼自己不知道的事。羅馬人、蒙古人和阿茲特克人之所有積極四方征討,為的是權力和財富,也不是為了新知。相較之下,歐洲帝國主義之所以要前往遙遠的彼岸,除了要擴張新領土,也是為了新知識(p.316)
  19. 現代科學和現代帝國背後的動力,都是一種不滿足,覺得在遠方一定還有什麼重要的事物,等待他們去探索、去掌握。然而,科學和帝國之間的鏈結還不僅如此而已。兩者不只動機相同,連做法也十分類似。對現代歐洲人來說,建立帝國就像是一項科學實驗,而要建立某個科學學門,也像是一項帝國大業。(p.331~332)
  20. 現代的生物學家已經可以指出,「所有人類族群之間的生物差異,小到可以呼略不計」,種族主義的論調可以輕鬆被推翻。(p.339) 

2019/04/02

[閱讀筆記] Value Investing: From Graham to Buffett and Beyond (7/7)


  1. Seth Klarman 提醒:價值投資的目的不是在牛市中跑贏大盤。在牛市中,任何人都可以做的很好,往往比價值投資者更好。只有在熊市中,價值投資法則才顯得特別重要,當令你安心的標誌不見了的時候,它可以幫助你找到方向
  2. 未來是不可知的,任何以預測未來股價走勢的投資行為,都是一種賭的行為,這是相當高風險的投資行為
  3. 保留部分現金是可以幫助我們創造更好的(獲利/風險)比率
    1. 大部分好公司股價被高估時 → 市場行情好 → 沒有標的可買或是選擇賣出被高估的手中持股 → 現金持有率變高
    2. 大部分好公司股價被低估時 → 市場行情壞 → 許多好標的可以買進 → 現金持有率變低
  4. 價值投資不是短跑競速,而是馬拉松
  5. Benjamine Graham 於市場先生(Mr. Market)的隱喻:「會對可能遭受50%損失而感到渾身不舒服的人,不該投資股票」。即使帳面的虧損可能讓人迷失方向,但長期的價值終究會不證自明。假如一個投資者賣出持有的資產時(無論是出於金錢、或是心理因素的考量),都必須思考:他們會在金錢、或是心理層面上得到什麼、以及必須放棄什麼(一個被顯著低估的機會)。
  6. 當你在思考潛在回報 (potential return) 的時候,記得先計算潛在風險
  7. 根據心理學家的研究發現,投資人對於損失的感受較獲得來得更加強烈。這其實是很有道理的,獲利 50% 的價值遠低於損失 50%,例如股價從 100 元跌落到 50 元,你損失了 50 元;但是從 50 元上漲 50% 75 元,你只有獲利 25
  8. Seth Klarman的投資方式是建立在三個基礎上
① 專注在報酬之前,先專注在風險 (evaluate risk first)
  • 風險不是波動性(volatility),波動性創造機會。 風險是虧損的機率,還有在虧損的情況下你能承受多少損失
  • 一個擁有 10% 潛在報酬率且低風險的投資標的,會比另外一個擁有 15% 潛在報酬率且高風險的投資標的來得有吸引力
② 專注在絕對報酬而非相對報酬
  • 因為很多經理人績效是跟指數比較,他們怕落後指數因而做出不佳的決策。
  • Seth Klarman 的基金不跟任何指數比較,若是找不到好的投資機會,就持有高比例現金。
③ 由下而上(bottom-up) 而不是由上而下 (top-down)
  • Top-down investors 通常會看大環境的變化,試圖了解產業週期、預測科技長期趨勢,挑選特定股票
  • Value investors bottom-up investors,這種選股評估方式認為,即使整體經濟景氣再壞,都一定有廠商與企業賺錢,即使經濟再繁榮,也會有企業經營不善而倒閉,因此,就一個股市投資者而言,要做的就是在茫茫股海中,找出一些公司真實價值(intrinsic value)被低估的、可以長期投資的績優企業個股。

  1. Michael Price 認為只要做對下列三件事,價值投資即可成功:
    1. 股價低於資產價值( A company selling at a discount from asset value)
    2. 公司經營階層持股越高越好( a management that owns share, The more, the better)
    3. 乾淨的資產負債表,負債愈少愈好( A clean balance sheet ,little debt so there is less financial risk)
  2. Michael Price 認為「投資的關鍵是抵禦熊市下跌,而不是牛市要跑贏市場
  3. Michael Price 認為,投資人應先降低風險,高收益自然跟著來。如果你在 down years 的表現不要太差,你只要在 up years 表現一般,就可以取得長期優於平均的報酬表現。
  4. Wall Street 需要替投資市場產生興奮劑,這樣投資公司 (investment firms) 才能賺錢。這場遊戲將會激勵投資人更加貪婪而非恐懼,value investors 應在在旁邊觀看,而非受到慫恿
  5. Michael Price 建議要「耐心等待廉價股票」,其投資方法有:
Discipline
(遵守紀律)
  • 不要偏離估價標準,不要因為其他投資方法更為流行,就改變自己的投資組合
Patience
(保持耐性)
  • 於分析並確定股票的內在價值後,如果發現股價並未達到比內在價值低40%的水平,該股就不算是廉價股票。為確保投資的安全,投資者應保持耐性,一直等到價格跌幅達到標準才購入該股。
Focus
(聚焦於投資標的)
  • 公司的細節及消息,比宏觀經濟預測更值得投資者關心。
  • 了解一家公司比了解整體經濟狀況來得容易
Power
(知識就是力量)
  • 知識就是力量,你要做好功課,每個投資都是與你對做的一方所下的賭注,只有其中一方會是正確的,報酬都會流向對於證券了解更多、知道更早的一方。每位投資人都要想辦法增加對於投資相關知識的深度與廣度
  • 隨著每次的交易、套利,你就會增加自己的經驗與知識庫當你累積大量的知識厚,value investors 就能快速地掌握稍縱即逝的機會
  • 耐性是投資人的美德,但是當機會來敲門時,你也要快速地把握

  1. Edwin Schloss 用來判斷公司價值的特徵:
    1. 相較於實際的資產,公司的債務很少或完全沒有。這在公司被清算時能提供安全邊際。
    2. 價格低於帳面價值的20%。他根據現金、固定資產和其他有形資產來計算公司的帳面價值
    3. 良好的股利收益率
    4. 管理層持有大量股份。
    5. 管理階層誠實而正直,且未領取過多的報酬
    6. 不怕持有現金
    7. 在股利降低後買入。投資人往往對股利的下降過於敏感,這是投資的黃金時機。
  2. 巴菲特對 Edwin Schloss 的評價:「Schloss 的投資極為分散,曾擁有超過100支股票,他知道如何辨認那些價格遠低於價值的股票,這就是他所有的策略。他從不擔心今天是幾月,是星期幾或者是不是選舉年。他簡單地認為,如果一家公司的價值是1美元,而能夠以0.40美元買下它,未來一定會有好事發生。因此他一次又一次地採用同樣的策略。他擁有的股票比我還要多很多,他對公司的基本性質不感興趣。Schloss 不易受到他人影響。這也是他的優勢之一,沒有人能夠對他產生非常大的影響。」
  3. 現在投資理論常見的「錯誤」論調:風險能帶來報酬,只有增加投資組合的波動性才能獲得更高的報酬
  4. Edwin Schloss 認為有句話說的好,「只有買入以後才能全面瞭解一隻股票」。這句話很對。買入之前是以旁觀者的身份看股票,不會太認真看。買入之後就不一樣了,原來沒發現的缺點都看的更清楚了。當然了,持有一段時間後,也會發現開始沒看出來的機會。
  5. Edwin Schloss 認為:我們做投資最關鍵的就是根據價格高低決定買不買,正如 Graham 在《Intelligent Investor》中所說,“買股票要像買菜一樣買,不能像買香水那麼買”。總之,我們喜歡買入我們認為低估的股票,而且我們必須有勇氣越跌越買。你必須獨立判斷,有勇氣堅持到底,市場不看好你的股票不代表你是錯的。話說回來,具體如何判斷,每個人必須自己決定。股市的魅力就在這,只有在未來我們才能知道答案。
  6. 當投資人感到失望時,股價就會下跌。投資人感到失望可能是對於最近的營收報告低於預期感到失望,或是對於連續令人不滿意的營收表現,導致投資人 (甚至是有耐性的投資人) 拋售股票。通常,這時候就會是個清倉大拍賣的好價位出現的時刻
  7. Schloss 自己也坦承自己常在一開始買進的時候買太多,當股價繼續下跌時,沒有足夠的資金買進更多。這也是 value investor 常犯的買太快與賣太快 (buy too soon and sell too soon)Schloss 也不例外。便宜的股票往往會變成更便宜;當其營運績效開始恢復與改善時,此時的股價也不是個便宜的買進點了。投資人也不必太過懊惱,總是有其他可以投資的地方。即便實現損失很心痛,然後就讓令人失望的股票作為你犯錯的提醒
  8. Eugene Fama提出「效率市場假說」(Efficient-market hypothesis)的定義是:如果在一個證券市場中,價格完全反映了所有可以獲得的信息,那麼就稱這樣的市場為有效市場。而群體的智慧(The wisdom of crowds),是集結個人的意見進而轉化為決策的一種過程。它是從許多個體的合作與競爭中湧現出來的。群體的智慧是市場效率中三個重要因素的主要基石,這三個因素為「充分被揭露、傳播並合併至市場價格」。每個人使用不同的分析方式、評價標準,或不同的模型,市場中每個人都獲得相同的資訊,並擁有獨立思考,決策的能力,市場才有可能是有效率的。但是為什麼市場還是有可能發生錯價的情況?因為投資人的情緒影響了他們的決策行為。
  9. 在證券分析中,葛拉漢寫道,「市場價格並非自動回復機制,而是由買家與賣家的心態與決策行為所構成」。所以葛拉漢以「市場先生」(Mr. Market)來形容影響市場價格起伏,恐懼和貪婪的情緒因子。
  1. Paul Sonkin 認為:小企業 (small companies) 較容易被理解、他們的財務報表與商業模式也叫為單純,通常只會有一個產品線,不像 S&P 500 指數內的公司都擁有 5 ~ 15 個產品線。而且,小企業通常擁有較少的競爭者與較小的主要客戶,小企業較能靈活地掌握市場的改變與新機會,因此研究小企業所花的時間之邊際價值遠超大公司。
  2. Paul Sonkin 認為:分析師們較少注意小企業。小企業的資訊和前景較不為人知,如果有分析師着手研究公司,他們會去研究大公司,而非小企業。花時間在分析投資於小企業上,自然比投資於大公司更易獲利。因此對價值投資者而言,小企業可說是一片有待開墾的肥沃土地。