Total Pageviews

2017/06/01

[閱讀筆記] The Black Swan: The Impact of the Highly Improbable (1/3)


  1. 黑天鵝的三大特性
    1. rarity (罕見):過去的經驗讓人不相信其出現的可能
    2. extreme impact (造成重大衝擊):只要一發生,就會造成重大的衝擊
    3. retrospective predictability (事後諸葛);一旦發生,人會因為天性使然而作出某種解釋,讓這事件成為可解釋或可預測
  2. 人們太少反思自己所相信、習以為常的事情
  3. 人類是相當膚淺的動物,我們都知道預防重於治療,但是我們通常不會去讚賞做風險預防動作的人,反而會去讚賞壞事情發生後去收尾的人
  4. 我們的世界是被極端、未知、無法預測的事物所主宰,然而人們卻聚焦在已知、重複發生的事物上
  5. 我知道誰的言論是錯誤,但是不代表另外一個言論是正確的。如果我看到一隻黑天鵝,我可以確定不是所有的天鵝都是白的。如果我看到有人殺了人,我可以幾乎確定他就是罪犯;但是如果我沒有看到他殺人,我無法確定他是無辜的。
  6. 我們總是假定歷史是是根據某種邏輯產生的,但是其實我們只有看到一連串的事件,不是邏輯,只是在猜測這一連串的事件是怎麼產生的
  7. 黑天鵝會出現是,人們聚焦於少量的不確定的來源,但是災難卻是從非聚焦的地方所產生
  8. 真實的世界是非線性的,而且會比你想得更非線性。線性的關係在真實世界是非常罕見的,你只會在教室或是教科書裡面才會看到,因為那是要讓你更容易理解
  9. 感恩節之前的火雞會因為被人類飼養對人類的信任度慢慢提高,如果你是火雞會認為自己沒有任何危險,直到感恩節那天,火雞的"黑天鵝"發生(超出它想像的事件),莫名其妙的被做成感恩節大餐
  10. 在真實世界裡,人們總是會較重視 What I did for you,較漠視 what I avoid for you。人們會看到911事件後對罹難者家屬的照顧,卻不會看到立法強制開車要繫安全帶,保護你人生安全的立法者
  11. 當你看到某個事件發生的原因是"因為"什麼樣的關係所導致,對於這個原因,請先保持懷疑的態度,小心求證
  12. 人是一個很膚淺的動物,只會注意到所看到的事物
  13. 為什麼我們會看不見黑天鵝,因為我們只擔心過去已經發生的事情,忽略了之前沒發生過的事情。這是因為人們對於沒發生過的、沒看過的事物,太過抽象,以致於忽略它、無法從中學習到教訓。
  14. 人類的知識會逐漸增加,但是威脅人們的是快速增加的自信。人類的傲慢源自於其有限的知識,人們總是高估自己所知道的,而低估不確定性
  15. 人類實際知道的知識,與自己認為自己知道的知識,常常有顯著落差
  16. 很多專家的預測並不準確,因為他們是根據不會重複發生的過去,來預測未來。我們頂多可以透過網站,預測明天戲院幾點開門
  17. 專家最大的問題是,他們不知道他們哪裡不知道
  18. 預測要正確,事情的發生要有規律性,如果沒有規律性,預測勢必失敗
  19. 人們常把成功歸因於自己的能力,把自己的失敗歸咎於外在的、無法控制的隨機事件。我們只對好的事物負責,對壞的事物卸責
  20. 因為我們不夠了解未來,所以我們無法做好妥善規劃。所以,在規畫的時候要牢記,我們規劃的限制是什麼

2017/05/31

2017/05 Travel

新店獅頭山步道
DSC01519

DSC01521

DSC01531

「印象.左岸–奧塞美術館30周年大展」 - 梵谷《午睡》
「印象.左岸–奧塞美術館30周年大展」 - 梵谷《午睡》


基隆港
IMG_6409




2017/05/13

[Mac] 使用 Safari 報稅時,一直卡在系統登入畫面

Problem
當我使用 Mac Safari 連上 https://rtn.tax.nat.gov.tw/ircweb/index.jsp 要使用自然人憑證進行報稅時,一直卡在此系統登入畫面


How-to
解決步驟如下
(1) Safari -> 偏好設定


(2) 安全性-> 外掛模組設定


(3) 點選 Java


(4) 將 rtn.tax.nat.gov.tw 此網站從關閉改為開啟,並按下完成


(5) 重新使用自然人憑證進行登入


(6) 按下繼續,即可開始報稅






2017/05/10

[webMethods] IS Package Class Loaders 順序

根據 webMethods 文件
  • IS package class loaders 順序是下圖的 1.1 ~ 1.4
  • 在 runtime 的時候,順序是下圖的 2.1 ~ 2.3
  •  要注意的是,若有一個檔案同時存在於 jars 與 classes 的 folder,位於 jars folder 內的檔案擁有優先權


以 Acme package 為例子,目錄結構如下:


Reference
[1] https://goo.gl/46NgNp

2017/05/09

[webMethods] 如何在 Java Service 中印 debug log

Problem
假設我在 Java Service 中印出 debug log 來進行程式碼的 debug,該如何印

How-to
若是同步的作業,作法如下:
    public static void logger(String message) {
    
        IData input = IDataFactory.create();
        IDataCursor inputCursor = input.getCursor();
        IDataUtil.put(inputCursor, "message", message);
        IDataUtil.put(inputCursor, "function", "customLogger");
        IDataUtil.put(inputCursor, "level", "INFO");
        inputCursor.destroy();
    
        try {
            Service.doInvoke("pub.flow", "debugLog", input);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

若是非同步的作業,作法如下:
    public static void loggerAsync(Session session, String message) {
        IData input = IDataFactory.create();
        IDataCursor inputCursor = input.getCursor();
        IDataUtil.put(inputCursor, "message", message);
        IDataUtil.put(inputCursor, "function", "customLogger");
        IDataUtil.put(inputCursor, "level", "INFO");
        inputCursor.destroy();
    
        try {
            Service.doThreadInvoke("pub.flow", "debugLog", session, input);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


以下是列印 log 的呼叫方式:
    // 非同步作業的呼叫方式
    Session session = Service.getSession();
    loggerAsync(session, "Hello~ asynch log");
    
    // 同步作業的呼叫方式
    logger("Hello~ log");







2017/05/08

[webMethods] 如何在 Java Service 中呼叫另外一個 Java Service

Problem
假設我有兩個 Java Service,一個為 Test Java Service: input 參數為 name,執行時會出現 popup window 供輸入


另外一個為 HelloWorld,input parameters 有兩個,分別是 name 與 dateTime,由Test Java Service 傳送給 HellowWorld Java Service,welcomeMessage = name + "(" + dateTime + ")"



How-to
可以使用 Service.doInvoke 來呼叫其他 Service
以下是 Test Service 中的 code snippet:
public final class Test_SVC

{

    /** 
     * The primary method for the Java service
     *
     * @param pipeline
     *            The IData pipeline
     * @throws ServiceException
     */
    public static final void Test(IData pipeline) throws ServiceException {
        IDataCursor pipelineCursor = pipeline.getCursor();
        
        // Invoke the pub.date:getCurrentDateString service to get current date time
        String currentDateString = "";
        IDataUtil.put(pipelineCursor, "pattern", "yyyy/MM/dd HH:mm:ss");
        try {
            IData data = Service.doInvoke("pub.date", "getCurrentDateString", pipeline);
            currentDateString = (String) IDataUtil.get(data.getCursor(), "value");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        
        // input name
        String name = IDataUtil.getString(pipelineCursor, "name");
        IDataUtil.put(pipelineCursor, "name", name);
        
        // get current date time via pub.date:getCurrentDateString service
        IDataUtil.put(pipelineCursor, "dateTime", currentDateString);
        
        // Invoke HelloWorld service
        try {
            Service.doInvoke("acme.albert.work", "HelloWorld", pipeline);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        
        pipelineCursor.destroy();
    }
}    


以下是 HelloWorld Service 中的 code snippet:
public final class HelloWorld_SVC

{

    /** 
     * The primary method for the Java service
     *
     * @param pipeline
     *            The IData pipeline
     * @throws ServiceException
     */
    public static final void HelloWorld(IData pipeline) throws ServiceException {
        // pipeline
        IDataCursor pipelineCursor = pipeline.getCursor();
        String name = IDataUtil.getString(pipelineCursor, "name");
        String dateTime = IDataUtil.getString(pipelineCursor, "dateTime");
        logger("dateTime = " + dateTime);
        
        pipelineCursor.destroy();
                
        // pipeline
        IDataCursor pipelineCursor_1 = pipeline.getCursor();
        String welcomeMsg = "Hello~" + name + " (" + dateTime + ")";
        logger("welcome msg = " + welcomeMsg);
        IDataUtil.put( pipelineCursor_1, "welcomeMessage", welcomeMsg );
        pipelineCursor_1.destroy();     
    }
    
    // --- <<IS-BEGIN-SHARED-SOURCE-AREA>> ---  
    public static void logger(String message) throws ServiceException {
        IData input = IDataFactory.create();
        
        IDataCursor inputCursor = input.getCursor();
        IDataUtil.put(inputCursor, "message", message);
        IDataUtil.put(inputCursor, "function", "customLogger");
        IDataUtil.put(inputCursor, "level", "INFO");
        inputCursor.destroy();
    
        try {
            Service.doInvoke("pub.flow", "debugLog", input);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }
    
    // --- <<IS-END-SHARED-SOURCE-AREA>> ---

}

執行結果:
[9987]2016-11-16 15:52:31 TST [ISP.0090.0004I] customLogger -- welcome msg = Hello~Albert (2016/11/16 15:52:31)
[9986]2016-11-16 15:52:31 TST [ISP.0090.0004I] customLogger -- dateTime = 2016/11/16 15:52:31

上述的範例是採取 synchronous 的方式去呼叫另外一個 Java Service,若要採用 asynchronous 的方式呼叫,需要改寫如下:
    Session session = Service.getSession();
    
    IData input = IDataFactory.create();
    IDataCursor inputCursor = input.getCursor();
    IDataUtil.put(inputCursor, "input", "hello");
    inputCursor.destroy();
    
    Service.doThreadInvoke("acme.albert.work.OPC", "OPC_Heartbeat_Flow", session, input);

2017/05/07

[webMethods] 在 Flow Service 中使用 Sequence 來實現 try-catch

步驟 1. 建立一個 SequenceFlow,並建立兩個輸入參數 num1 與 num2,將 num1 * num2 的結果傳送到輸出參數 result


步驟 2. 建立三個 Sequences,try-catch, try 與 catch,此三個 sequence 的 Exit on 參數分別為
* ‘Success’ for the ‘try-catch’ sequence.
* ’Failure’ for the ‘try’ sequence.
* ‘Done’ for the catch sequence.


步驟 3. 在 try-sequence 中加入 multiplyInts 進行運算


步驟 4. 在 catch-sequence 中加入 getLastError 來取得例外錯誤訊息,並加入 debugLog 將錯誤訊息印到 server log


步驟 5. 執行並驗證結果

2017/05/06

[webMethods] 在 Flow Service 中使用 Loop

步驟 1. 分別建立 OrderRequest 與 OrderResponse Document ,Request 與 Response 的資料結構相仿,唯一差異的地方是 Response 的 Subtotal = Request 的 Quantity * Price

步驟2. 建立 LoopFlow,並將 input 與 output 分別設定為 OrderRequest 與 OrderResponse

步驟 3. 在 LoopFlow 中,分別加入 MAP、LOOP、MAP 與 MAP,並在 LOOP Step 中設定 Input array 與 Output array


步驟 4. 在 LOOP 中進行 MAP Request 與 Response data,並加入 multiplyInts transformer 來運算 Quantity * Price = Subtotal

步驟 5. 執行 LoopFlow 並查看結果










2017/05/05

[webMethods] 在 Flow Service 中使用 Branch

步驟 1. 建立一個 Math Flow,用來展示加減乘除的數學運算


步驟 2. 建立 input / output parameters,num1 與 num2 是供輸入的兩個整數參數,operator 是輸入加減乘除用的參數,result 是運算結果


步驟 3. 在 MathFlow 中,建立一個 branch step,依照 operator 參數所輸入的值來做不同的處理


步驟 4. 依據不同的 operator 使用不同的套件,即 pub.math:addInts, pub.math:subtractInts, pub.math:multiplyInts, pub.math:divideInts,Label 的值代表是 operator 所輸入的值


步驟 5. 在 pipeline tab 拉 pub.math:addIntspub.math:subtractIntspub.math:multiplyIntspub.math:divideInts 對應的值








步驟 6. 若 operator 輸入非預期的字元,則要做額外的處理,label 設定為 $default,並設定印出 The operator is invalid 此警告訊息




步驟 7. 若 operator 沒有輸入值,,則要做額外的處理,label 設定為 $null,並設定印出 The operator is null 此警告訊息





執行結果




2017/05/04

[webMethods] 刪除 Flow Service 中不需要的參數 - Drop the Selected Variable

假設以下是一個已經完成的 Flow Service,Pipeline Out 那個 column 代表著執行此 Flow Service 會產生的三個 output parameters:



Run Flow Service 的結果如下:



若我們希望 Pipeline Output 只要有 document 物件就好,其餘兩個 parameters 不要顯示,可以在 Pipeline tab 選定 parameter(s),再點選 Drop the Selected Variable 並儲存即可



若是要還原的話,操作如下:

2017/05/03

[webMethods] 如何將 JSON String 轉換成 ESB 中的 Document 物件

我有一個 Service Class,可以透過 buildTestJson() 取得測試用的 JSON String,或者是呼叫 buildHeartbeatMsgJson() 並傳入一個 HBMessage 物件取得 JSON String
import java.io.Serializable;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OpcHeartbeatService {
    
    private final static Logger logger = LoggerFactory.getLogger(OpcHeartbeatService.class);
    
    public static void main(String[] args) {
        OpcHeartbeatService test = new OpcHeartbeatService();
        logger.info("buildTestJson = " + test.buildTestJson());
    }
    
    public String buildTestJson() {
        HBMessage hb_msg = new HBMessage("test", "123445", "HBT_MSG");
        return buildHeartbeatMsgJson(hb_msg);
    }
    
    public String buildHeartbeatMsgJson(HBMessage hb_msg) {
        JSONObject dataset = new JSONObject();
        
        JSONObject hbObject = new JSONObject();
        hbObject.put("serviceId", hb_msg.getServiceId());
        hbObject.put("token", hb_msg.getToken());
        hbObject.put("type", hb_msg.getType());
        
        dataset.accumulate("heartbeatMsg", hbObject);
        
        return dataset.toString();
    }

    public static class HBMessage implements Serializable{
        private static final long serialVersionUID = 1L;
        
        private String serviceId;
        private String token;
        private String type;
        
        public HBMessage() {
            super();
        }

        public HBMessage(String serviceId, String token, String type) {
            super();
            this.serviceId = serviceId;
            this.token = token;
            this.type = type;
        }

        public String getServiceId() {
            return serviceId;
        }
        
        public void setServiceId(String serviceId) {
            this.serviceId = serviceId;
        }
        
        public String getToken() {
            return token;
        }
        
        public void setToken(String token) {
            this.token = token;
        }
        
        public String getType() {
            return type;
        }
        
        public void setType(String type) {
            this.type = type;
        }
        
        @Override
        public String toString() {
            return "HBMessage [serviceId=" + serviceId + ", token=" + token + ", type=" + type
                    + "]";
        }
    }
}



在 Design 中建立一個 Java Service,名為 OPC_Heartbeat




在 OPC_Heartbeat 中定義一個 output 參數 (i.e. heartbeatJson),用來接收 buildTestJson() 所得到的 JSON String




在 OPC_Heartbeat 中,呼叫 OpcHeartbeatService 的 buildTestJson() method,取得測試的 JSON String ,並將 JSON String 傳給 output parameter
public final class OPC_Heartbeat_SVC

{

    /** 
     * The primary method for the Java service
     *
     * @param pipeline
     *            The IData pipeline
     * @throws ServiceException
     */
    public static final void OPC_Heartbeat(IData pipeline) throws ServiceException {
        OpcHeartbeatService hbService = new OpcHeartbeatService();
        String hbJson = hbService.buildTestJson();
        
        IDataCursor pipelineCursor = pipeline.getCursor();
        IDataUtil.put(pipelineCursor, "heartbeatJson", hbJson);
        pipelineCursor.destroy();
    }
    
    // ignore......
}    



OPC_Heartbeat 執行結果




將 OPC_Heartbeat 拉近 Flow Service,並利用 pub.json:jsonStringToDocument 此現成套件協助我們將 JSON String 轉成 ESB 中的 Document 物件




2017/05/02

[閱讀筆記] 惡魔財經辭典 (The Devil’s Financial Dictionary) [1/6]


  1. 大多避險基金收取一般共同基金十倍的費用,然後交給投資人指數型基金一半的報酬。事實上,避險基金沒什麼特別厲害之處,它們大多帶來令人失望的報酬
  2. 運氣、不確定、意外,是投資的基本外力,而華爾街在在跟外界溝通時,往往否定這些外力的威力
  3. 愈是濃縮、音節愈多的行話術語,愈有可能隱藏不想讓你知道的事。抓住男人的胃或許可以抓住他的心;要撬開投資人的口袋,就得從他的耳朵下手
  4. 金融歷史事件不會完全一模一樣重現,但也相去不遠。不管別人多大聲告訴你這次不一樣,人性是不會改變的。趨勢來來去去,唯一不變的是手續費永遠要繳
  5. 上漲的,遲早會下跌(通常比大家預期的還要早);同樣的,下跌的,也一定會再度上漲(通常是在專家都說不會的時候)
  6. 華爾街賣的是股票和希望,不過真正兜售的是『希望』。投資大眾都希望有奇蹟存在,於是金融業者就不斷宣稱看得到未來、能實現奇蹟。無論如何,千萬別跟著那些人走
  7. 所謂理財成功,並不是在金融遊戲中打敗專業,而是做到自我克制。金融市場每隔幾年就來一次的狂喜或絕望之時,退一步冷靜思考
  8. AAA 等級的債券不能保證你不會賠錢,2008年前三季,有超過 11000 個 AAA 等級房貸有價證券突然遭到大幅修正,其中許多證券的價格跌了七成或更多,導致投資人損失數千億美元
  9. 銀行機構每個月或每一季寄給你的帳戶明細(account statement),會盡量隱藏、偽裝虧損與費用的部份,讓你把注意力放在收入或獲利上
  10. 股市並不是一股一致的力量,不會採取一致的行動;股市是一種機制,看相反的人在其中就彼此的差異取得價格共識
  11. Alpha 係數是指高於市場指數的投資報酬率,通常用來表示投資經理人的選股技巧與能力,但事實上 alpha 幾乎只是隨機偶發的結果
  12. Amortize 有攤提的意思,一即將開支平均分攤一段時間,直到分攤完畢為止。如一支共同基金得先付 5.75% 的手續費,看起來很多。但是如果你 amortize 到未來 25 年,每年才付 0.23% ,就可以得到我未來 25 年的顧問服務,真的很划算喔
  13. 分析師理論上會拆解、分析一家公司的組成,並估算其價值。但實際運作起來,卻變成該公司的推銷員、啦啦隊
  14. 分析師常用的定錨(achor )手法是,為一支股票設定遠高於或遠低於市場價格的目標價,然後這個數值就會深植於投資人的腦中,就像定住的錨一樣,讓他們不去思考目標價合不合理,就能逐漸把該股票的價格拉往目標價
  15. 一年一度的股東大會,公司經營高層常用來粉飾業績,假裝用心傾聽股東的願望和抱怨
  16. Anomaly (異常現象)是一種投資策略或評估技術,可以產生高於大盤的報酬率,而且沒有明顯的高風險。但是不管在哪裡找到的 anomaly,都必然帶有自我衰敗的種子,因為這只是統計上的偶然而已,當大家把資金湧入、如法炮製,潛在的報酬率也隨之降低,最後就會回歸到平均值
  17. 資產配置據說是一門科學,不過很多理財顧問並不是用數學或邏輯來推薦資產配置,而是全憑猜測,或是最近什麼商品熱門就推薦什麼
  18. 若有人向你推薦某個資產配置,務必要問問其中有哪一項曾經報酬率很低。如果都沒有,那對方根本不是在推薦什麼資產配置,而是在邀請你追逐某種熱門投資,而且極可能馬上變得不熱門了
  19. 投資的各種類別各有不同的風險和報酬率,彼此之間的關聯性不高。例如股市表現不佳時,債券往往表現很好,反之亦然;股市或債市的走勢若急轉,期貨行情有可能也會急轉
  20. 如果有某一種「新的」或「另類的」的資產類別(asset class),其持有成本高於股票和債券等傳統資產類別,那麼,其價值大概也不會維持太久
  21. 大部分的理財顧問都盡可能從越多客戶身上搜刮越多的資產,這樣就能以最少的工作量賺到最多的手續費
  22. 股市崩盤很罕見,但是造成的驚人損害會烙印到集體意識中,導致投資人錯失在非崩盤期間(上次崩盤到下次崩盤之間其實非常長)靠股票謀利的機會
  23. 絕大多數的 IPO (Initial Public Offering)都不會比大盤好賺,不過,只要有少數引人注目的 IPO 一飛沖天 (如 Google IPO),就會造成投資 IPO 可以致富的假象
  24. 對股價走勢極有影響力的紅牌分析師(axe),會一直換人,當舊的紅牌不準時,就會出現新的紅牌,這種詭異的狀況一直重複上演,而大多數的投資人卻沒發現。其實 axe 都撐不了太久,不用太認真對待
  25. 理財顧問常從Backtest (歷史回測)得出的大發現,只不過是統計上的僥倖罷了,這只會出現在樣本中,無法代表全體。
  26. 當理財顧問提出一些令人經驗的歷史數據給你,你該問幾個問題
    1. 這些數據是 backtest 嗎?
    2. 這些是多久以前的數據?
    3. 你是什麼時候開始用真正的錢實際操作這個策略?
    4. 你有更改過這項策略嗎?如果有為什麼?
    5. 決定採用這個策略前,你還試過其他多少策略?
  27. 價格走跌階段必然也意味著日後會有上漲階段。一般認為,股市平均下跌至少 20% 就算是 bear market 的開始,不過其實也沒有什麼正式的定義或門檻
  28. 一心想要 beat the market (打敗大盤)的人,通常都會被大盤所打敗
  29. Beta 係數是指某一支股票的報酬率跟大盤指數報酬的連動性。例如如果某一檔股票的 beta 係數是1.0,當大盤指數上漲 10% 時,該股票的報酬率則為 10%;若 beta 係數是 1.5 ,該檔股票在指數下跌 10% 時,會虧損 15%。依此類推, beta 係數越高,風險和報酬也越高。不過這參考看看就好,風險的部分是屢試不爽,報酬的部份則是難得一見
  30. 企業可透過操控可調節的會計項目,提前或過度認列費用和成本,以製造後來營利回彈的假象