2013年7月31日 星期三

年複合成長率

年複合成長率常在新聞或理財書籍中看到, 今天在寫 "看懂新聞 2" 的閱讀筆記時, 剛好看到這詞彙, 找了一下網路資料 (如下), 原來就是用複利的觀念來看成長率, 複利公式 :

FV=PV(1+i)**n          終值=初值(1+利息)**周期

年複合成長率就是反求複利公式中的利息 :

i=(FV/PV)**(1/n)-1  

也就是終值除以初值, 開 n 次方後, 再減 1 即得.

例如台積電的損益表, 2003 年營收為 2030 億, 2012 年已成長為 5063 億, 平均每年成長 (5063-2030)/10=303.3 億, 平均成長率為 303.3/2030=14.94%, 十年來其年複合成長率為 9.41%. 可見平均成長率會比較大, 保險業務員常拿平均成長率來跟客戶說利息有多高, 但以年複合成長率來算, 就沒這麼高了.

我把這公式寫成 PHP 程式如下 :

年複合成長率 : http://mybidrobot.allalla.com/finance/cagr.php [看原始碼]

$PV=(float)$_REQUEST["PV"];
$FV=(float)$_REQUEST["FV"];
$n=(float)$_REQUEST["n"];
if ($PV != 0 && $n != 0) {
    $cagr=round((pow($FV/$PV,1/$n)-1)*100,2);
    echo "初值=$PV<br>終值=$FV<br>周期=$n<br>".
             "年複合成長率=$cagr%<br>".
             "<input type='button' value='回上一頁' ".
             "onclick='history.go(-1)'>";
     }
else {      
     echo "初值與周期不可為 0<br>".
              "<input type='button' value='回上一頁' ".
              "onclick='history.go(-1)'>";;
      }

參考資料 :

** 請問什麼是年複合成長率(CAGR, Compound Annual Growth Rate) ?
** 複利

專案進度 : 停掉 cron

因為 stockbot.x90x.net 被停權了, 但每天還是會收到空信, 所以晚上把 cron 清掉, 同時把 gaetrader (webabc999) 的 cron 也停掉, 以免沒用的 mail 一堆.
這兩天整理讀書心得, 所以專案沒什麼進度. 看懂新聞 2 這本書有人預約, 本週要還, 所以閱讀筆記要優先寫完.

大咪打疫苗

中午打電話回家時, 媽說早上載大咪去廟裡打狂犬病疫苗, 整個廣場人山人海, 都是~~狗, 貓比較少, 我想可能是貓比較少綁起來, 不容易抓去打針.
上個禮拜天, 爸就把大咪關進籠子裡, 不讓牠往外跑, 他一向自由慣了, 從沒被關過, 待在籠子裡看來挺難受的, 只要有人走近就發出可憐的低沉喵嗚聲.

2013年7月29日 星期一

當機長感到恐慌時

新聞說, 前疾管局長在臉書抨擊政府處理狂犬病問題過度樂觀, 證諸這幾天全台各地都已證實有野生動物感染, 相信以現在還漫不經心的作為, 全國淪陷恐怕將是不可避免之事. 當機長以恐慌的口吻廣播說, 左引擎失效, 請繫好安全帶時, 身為乘客的全國民眾, 這時應該感到恐慌嗎?
這個農委會跟衛生署在搞甚麼? 都跟主子一樣在睡覺嗎? 633 騙人就算了, 冤冤枉枉至少還活得下去; 現在搞出狂犬病蔓延, 變成全國性恐慌, 難道這是當初投下神聖一票的共業?
之前李惠仁為了政府隱匿禽流感疫情而槓上農委會時, 我就感覺不妙了, 流行病學跟感控這等關係全民性命之大事竟然還要一個社會人士花費巨資去追蹤揭發, 這個國家還有救嗎?

2013年7月28日 星期日

專案進度 : 我的免費網站又掛點了

昨晚連線 stockbot 專案網站發現無法顯示, 登入後台才發現帳號又被 x90x.net 停權了, 原因是執行太多次 MySQL 查詢, 建議我升級為付費方案. 而我在 Appfog 的相同網站卻依然運轉良好, 我打算以後就轉移到 Appfog, 而 x90x.net 就用作純測試用吧.

FreeSuspendedAbuseAccount stockbot.x90x.net has executed more than 70000 MySQL queries that took more than 1 second to complete. Our shared hosting servers are not designed to host websites that create excessive or slow MySQL queries. Please optimize your website or move it to VPS / dedicated server  

GY 的主管

新聞說, 下士虐死疑案已將旅長改列被告, 因為他是核定關禁閉的最高主官. 據說昨天下士的連長向軍檢說, 不知道士官照規定不能送禁閉云云, OK, 當到連長還搞不清楚, 當旅長的不會不知道吧? 我不清楚到底這位旅長是怎樣情形下蓋章, 但可以從這新聞思考 :

  1. 主官的位子不是阿貓阿狗隨便能坐的啊! 更不能只是橡皮圖章, 屬下呈上來看都不看就蓋章, 這樣易為下屬欺瞞, 更明白透露一個秘密 : 你不是個精明的主管, 所以要呼弄你很容易. 做主管的要讓下屬清楚一件事 : 不要以為我都不懂, 不要以為我只看大的, 不看細節. 能明察秋毫, 會在細節挑出毛病的主管才能讓屬下兢兢業業, 不放過任何一個可能出錯的地方. 寧可被屬下背後罵 GY, 絕不能讓他們看輕你, GY 的主管才是讓屬下敬畏的主管. 至於說出 "基於信賴原則信任部屬" 這樣的話的人, 根本不夠格當主管, 更別說當肩膀上掛星星的將官了. 御下不難, 敬畏而已. 
  2. 雖然討厭法律, 但做主管的一定要清楚業務相關法律, 否則一旦觸法, 或碰上比你懂法律的對手, 你只有挨打的份. 記住, 法律只保護懂法律之人.



2013年7月27日 星期六

遊義大世界

今天帶菁菁跟椏晴去義大世界玩,刺激的她們都不敢玩,我都笑她們都玩一些學齡前的遊戲,像咖啡杯之類的。老實說,我也不贊成小朋友去玩雲霄飛車,因為過大的重力容易對發育中的腦神經產生不可預知的後果。像義大最刺激的 U 型軌道跟一字棒,老實說我也不太敢坐啊,太恐怖囉。

在摩天輪頂端

兩個高年級玩學齡前兒童遊戲

2013年7月25日 星期四

新舊電視

在燦坤買的 LG 42LM6400 液晶電視經一個多禮拜使用,感覺是棒呆了,尤其是HD台,影像好到連毛細孔都看得清清楚楚。如果有 MOD 或藍光,效果一定很不錯。
至於舊電視,我問了回收商,自己載過去是 $120,還真是沒價值啊。我是念舊的人,特地給它照了張相 :

LG 42LM6400 42" (2013.7.12~)

SANYO 29" (1996~2013)

變異係數與標準差

評估兩組數據的穩定度時, 譬如兩個企業的營益率變化, 應該使用變異係數, 而不是標準差, 因為不同公司的營益率會有不同水準. 根據維基的解釋 :

"變異係數只對由比率純量計算出來的數值有意義, 變異係數是一個無因次量, 因此在比較兩組因次不同或均值不同的數據時, 應該用變異係數而不是標準差來作為比較的參考。"

變異係數=標準差/平均值

變異係數 CV : http://mybidrobot.allalla.com/finance/cv.php [看原始碼]

我們用一個簡單程式來說明, 例如一組五個數據 : 100,100,100,100,100, 標準差與變異係數當然是 0, 如果其中一個數據由 100 降一半為 50,100,100,100,100, 那麼標準差是 22.361, 而變異係數是 25. 這跟 10,20,20,20,20 這組同樣是有一個數據降一半的變異係數是一樣的, 都是 25, 但這組標準差是 4.472. 所以看標準差是無法比較的, 要化成變異係數去比. 這種除以平均值的手法其實也就是所謂的正規化的一種方式, 所以, 變異係數可以說是正規化的標準差.

$arr=Array(50,100,100,100,100);
$sum=0; //總和
$square=0;  //平方和
$count=count($arr);
for ($j=0; $j<$count $j++) { 
       $sum += $arr[$j]; //和累計
       $square += pow($arr[$j], 2); //平方和累計 (計算標準差用)
       } //end of for
$avg=round($sum/$count,2);  //計算平均值
$std=sqrt(($square-pow($sum,2)/
$count)/($count-1)); //計算樣本標準差
if ($avg != 0) {$CV=round(100*$std/$avg);}  // //計算變異係數
else {$CV=9999;}  //表示極大值


2013年7月24日 星期三

專案進度:修改月營收追蹤程式

今天重新修改月營收追蹤程式, 除了近三月營收年增率均為正以外, 加入新的追蹤變數 :

(1).近三月營收年增率是否遞增
(2).近三月營收年增率是否負轉正
(3).近三月營收年增率是否遞減
(4).近三月營收年增率是否正轉負

長短期營收年增率變化方面, 由於今年實施 IFRSs, 所以擷取24個月資料會新舊雜陳, 沒有意義, 等明年資料一致後再寫.

瀏覽人數破萬

昨天注意到我的小狐狸事務所到站人數竟然破萬, 沒想到我的隨手記竟然有人會有興趣, 我看了一下流量統計, 發現最常被拜訪的, 原來是前陣子為了寫專案所撰寫的一系列 jQuery/jQueryUI 的測試文, 呵呵, 可見 jQuery 多紅啊! 最近沒時間再繼續寫 jQuery, 因為專案正如火如荼進行, 等寫完再繼續吧.

2013/7/24
 2013/4/30
2013/3/21

2013年7月23日 星期二

2013年7月21日 星期日

專案進度:修改股利政策

今天把股利政策程式做了大幅度修改, 不再從 Yahoo 抓資料, 同時每一支程式都加上測試模式, 只要在網址後面加上 ?id=股號, 就可以指定抓取該股資訊.

2013年7月19日 星期五

專案進度:完成現金流量表

昨晚把現金流量表搞定, 此表主要是觀察長短期 (3 年/8 年) 營運現金流與自由現金流, 分別計算其占稅後淨利之比率, 也就是所謂的稅後純益含金量, 營運現金占稅後淨利應大於 100% 為佳, 而自由現金占稅後淨利應大於 50% 為宜. 另外就是長期自由現金總和應為正, 過去 8 年中至少 5 年為正值.
另外, 由於 cron job 檔案越來越多, 放在根目錄下顯得很凌亂, 所以全部搬到 cron 資料夾, 當然 GAE 的 main.py 的 router 也隨同修改. 系統更新後目前看來跑得很順.

關於大埔拆屋

昨天苗栗縣長沾沾自喜說天賜良機, 調虎離山拆了大埔四戶. 前陣子偶然想起劉邦友案, 花了一些時間上網去研究, 此案原因眾說紛紜, 令我半信半疑. 今日又看到網路上這篇 :
劉邦友、劉政鴻的命運共同體
又讓我想起以前鄉下的前鎮長, 因為執行都更, 把一塊日據時代 (搞不好前清就有了) 的公墓全部拆遷, 闢為新鎮公所大樓, 結果沒幾年家中迭遭變故, 鎮長本人亦不久病故, 鄉人傳言可能拆遷公墓未處理好云云, 繪聲繪影令人對神鬼之說更添想像.
愚以為, 拆牛鬼蛇神之屋冒犯神威遭禍或有之, 但拆老弱婦孺之屋你不用替他擔心, 因為他心裡可能這麼想 : 你能拿我怎樣? 你是牛鬼蛇神嗎? 誰知道.
我同事說, 他不同情大埔被拆戶, 我覺得評論別人很容易, 如果是拆你的房子的話, 你全力配合?
恕我直言, 古來富者以土地致富最多, 都更, 土地重劃, 拆遷, 地目變更, ... 這些政治人物玩的把戲, 內行人才知道門道, 其中名堂絕非我等憨人想的哈尼甘單.

2013年7月18日 星期四

Win8 系統備份的方法

今晚跟姊姊去逛明儀, 主要是找一本 Win8 的書, 因為剛買的聯想 H520 桌電昨晚已做好系統更新, 但還沒做系統備份, 也不知道該如何使用, 至少要先了解如何關機吧 (據說這是 Win8 使用者最大的挫折). 選了老半天, 挑了上奇李慶宗的這本 "Windows 8 達標必備工具書".
回來第一件事當然是做系統備份, 這是在 "控制台/Windows 7 檔案修復" 中, 點選左邊的 "建立系統映像", 儲存備份的位置選 D 碟 (或 E 碟, 就是存資料的那個分割啦), 備份項目選 "讓 Windows 選擇", 這樣就 OK 了, 我做完 Win8 更新, 只安裝 Chrome 而已, 系統備份就用掉 37G, 恐怖啊.
做完系統備份, 還要按左邊的 "建立系統修復光碟", 放入一片空白 DVD 即可, 這是當 Win8 無法開機時用來修復系統的開機片, 若要從 D 碟的系統備份還原, 也是要用到這片修復光碟, 大約 300 多 MB.
至於控制台在哪裡? 這也是常忘記的, 在色塊介面中, 滑鼠移到右下角會出現選單, 按設定, 再選控制台就可以了.
除了備份, 最好也手動建立一下還原點, 這在 "控制台/復原" 中按 "建立還原點", 輸入還原點名稱, 例如 "Win8 更新完成" 即可.

 參考 :

# 如何建立 Windows 8 系統映像檔備份與還原




2013年7月16日 星期二

搞定數位電視

昨天燦坤派人來安裝新買的 LG 42LM6400 液晶電視, 哪知數位天線接上去竟然掃描不到信號, 但接回去舊電視就可以呀, 安裝師父說我原先給機上盒用的數位天線信號太弱, 機上盒有放大所以抓得到信號, 但直接接液晶就抓不到了, 建議我去買大通的天線, 趁著會招 22:00 才結束, 跑去燦坤買了大通圓盤型的天線, 又花了 $1090, 看在會招降價 $500 份上, 還是賺到了 (沒買賺更多吧).
結果昨晚馬上裝上去還真的有效, 馬上就掃到 6 台, 但這是天線移到室外, 若在室內僅 2 台, 所以燦坤店員說的沒錯, 買室內的都回來退, 改買室外型的.
不過內附電纜才 3 公尺, 太短了, 所以晚上又跑了一趟燦坤, 又花 $179 買了一捲 10 公尺的線, 跟二哥倆人一起拉線鎖到陽台鐵欄杆上, 哇, 效果超好, 掃到 16 台, 連我們這裡信號最弱的台視都掃到了, 影像超好, 呵呵, 值得值得.

PHP 計算日期差距的方法

使用 PHP/cURL 可以從 Yahoo 股市可以抓到一家企業的上市日期 $listed_date (注意是民國年), 但要計算這家公司已上市幾年, 這在 PHP 要怎麼寫? 翻了一下書, 發現其實這很簡單, 只要利用 time() 跟 mktime() 這兩個函數就可以辦到 :

//計算已上市年數
list($Y,$M,$D)=explode("/",$listed_date); //拆分 83/09/05 (年/月/日)
$Y=$Y+1911; //轉成西元年
$listed_time=mktime(0,0,0,$M,$D,$Y); //計算 1970/1/1 以來至上市日秒數
$listed_years=round((time()-$listed_time)/3600/24/365,1); //四捨五入至小數一位
echo "上市日期=$Y-$M-$D (已上市 $listed_years 年)";

其中 time() 是計算 1970/1/1 至目前之秒數, 減掉至上市日秒數, 就是上市至今的秒數, 除以 31536000 即得上市年數. 通常上市兩年以上的企業才值得進一步評估, 新上市股宜剔除.

2013年7月15日 星期一

專案進度

上週為了評鑑忙翻了, 每年這時都要接受考試, 雖然很討厭, 但也趁這機會建立幾個 SOP 也不錯, 反正無法躲避就要轉念.
這兩天專案有大大的進步, 完成損益表與資產負債表分析, 增加了營收市值比與市值淨值比這兩個指標的計算程式, 只剩下現金流量表了. 簡單紀錄一下.

買新電視

週六下午跑去全國電子跟燦坤看電視, 因為家裡那台已使用 16 年的三洋 26 吋傳統映像管電視已經快要報廢了, 雖然還勉強可看, 但亮度會忽亮忽暗, 剛好燦坤會員招待週有降價, 趁這機會換新的好了.
先在全國看了 42 吋 LG6200 3D LED 的聯網電視 $19999, 很心動. 但貨比三家不吃虧, 轉往燦坤也看到同型號的 LG, 但外觀不同, 價錢較貴 $23900, 但附贈無線網卡 (單買 $1900) 與藍芽喇叭 (單買 $6800), 刷卡滿 $30000 還回饋 $500 元提貨劵, 扣下來電視約 $15200, 感覺比較划算, 所以就決定在燦坤買了. 因為小朋友常要跟我搶電腦用, 所以添購一台廉價電腦, 剛好此次會招有一台聯想雙核 4G DRAM + 500G HD, 有 HDMI 輸出埠, 可以放在電視旁邊, 用電視當螢幕, 特價 $8888, 外加羅技無線鍵盤滑鼠組, 特價 $819, 這樣加起來一共 $33607, 分六期付款.
那台快壞的三洋電視, 記得是當初買房子時在大寮萬客隆連同洗衣機, 冰箱一起買的, 三年前洗衣機換了, 用了 13 年, 現在只剩下冰箱了, 門的磁性已經不佳, 有時不注意會沒關緊, 前陣子有打算要換, 但沒時間去看貨, 還能用以後再看吧.

菁菁上佛光山

昨天菁菁跟小安兩表姊妹參加佛光山夏令營, 為期四天, 還好颱風已漸歇, 沒有停課. 昨天下午突然狂風暴雨大作, 咦, 颱風不是走了嗎? 果然颱風尾比較驚人.

2013年7月12日 星期五

颱風來了

蘇力颱風逼近, 明天開始會有大風雨嗎? 台北下午放假, 南部目前還是悶熱天.


比對 PHP 主機與 GAE 的 log

昨天修改 x90x.net PHP 主機的 GAE cron job, 把 fetch_twse_daily_close 的執行時間由固定時點改為週期性 (每 61 分鐘), 今早把兩個主機的  LOG 撈出來比對, 發現昨天的結論是對的, PHP 免費主機的 uptime 不保證 99.99%, 如果是固定時點去 trigger, 失敗的機率是蠻高的; 人海戰術有效, 失誤率較低, 也就是說仍然可觀察到失敗的情況.

下面是 GAE 主機 twstockbot 在過去 13 個小時中的日誌 :

2013-07-12 08:40:11.807 /fetch_twse_daily_close 200 1747ms 0kb
2013-07-12 07:39:10.003 /fetch_twse_daily_close 200 3368ms 0kb
2013-07-12 06:38:06.520 /fetch_twse_daily_close 200 3519ms 0kb
2013-07-12 05:37:02.963 /fetch_twse_daily_close 200 617ms 0kb
2013-07-12 04:36:02.271 /fetch_twse_daily_close 200 3465ms 0kb
2013-07-12 03:34:58.725 /fetch_twse_daily_close 200 4060ms 0kb
2013-07-12 02:33:54.563 /fetch_twse_daily_close 200 3443ms 0kb
2013-07-12 01:32:51.055 /fetch_twse_daily_close 200 3815ms 0kb
2013-07-12 00:31:47.134 /fetch_twse_daily_close 200 1777ms 0kb
2013-07-11 23:30:45.305 /fetch_twse_daily_close 200 10405ms 0kb
2013-07-11 22:29:34.896 /fetch_twse_daily_close 200 14362ms 0kb
2013-07-11 21:28:20.443 /fetch_twse_daily_close 200 14276ms 0kb
2013-07-11 20:27:06.117 /fetch_twse_daily_close 200 9814ms 0kb

底下則是 x90x.net PHP 主機的執行日誌, 與上面比較, 可知在過去 13 個小時中失敗三次, 失誤率 23%, 這也驗證了昨天推測此主機的 uptime 大約 80% 左右  :

2013-07-12 08:40:11 fetch_twse_daily_close.php download 1 非交易日
2013-07-12 07:39:09 fetch_twse_daily_close.php download 3 非交易日
2013-07-12 06:38:06 fetch_twse_daily_close.php download 3 非交易日
2013-07-12 04:36:02 fetch_twse_daily_close.php download 4 非交易日
2013-07-12 03:34:58 fetch_twse_daily_close.php download 4 非交易日
2013-07-12 02:33:54 fetch_twse_daily_close.php download 3 非交易日
2013-07-12 01:32:50 fetch_twse_daily_close.php download 3 非交易日
2013-07-12 00:31:47 fetch_twse_daily_close.php download 2 非交易日
2013-07-11 23:30:45 fetch_twse_daily_close.php download 10 OK
2013-07-11 20:27:06 fetch_twse_daily_close.php download 10 OK

從回應時間可知, 時間太長 (似乎超過 10000 ms) 或太短 (似乎小於 1000 ms) 大概會有問題.
雖然沒有對 Appfog 主機進行相同的測試, 但昨日的兩個單一時點 trigger 都有順利執行, 感覺較穩, 我推測這可能是它跟 GAE 一樣以資源使用量來約制免費與收費的關係, 所以品質與收費可能一樣, 要再觀察一陣看看.




2013年7月10日 星期三

從 GAE 的 log 觀察伺服器回應是否正常

這幾天為了 GAE 的 cron job 老是沒能成功地在 15:00 從 PHP 應用程式擷取報告而苦惱, 原先懷疑 GAE 的 cron 是否有問題, 但檢查 log 都有正常 trigger, 後來又懷疑是網頁被 cache 了, 但經過調整 meta 為 nocache 還是無效, 每天 15:00 那一筆 cron_log 就是會 miss 掉, 連帶影響 15:10 的 create_daily_report 與 15:15 的 fetch_daily_report.
昨晚比對舊網站資料, 測試了一番也是徒勞無功, 於是仔細檢查 GAE 的 Logs, 再比對我的 cron_log 資料表, 發現很有可能是 PHP 主機問題, 因為我發現不只 fetch_twse_daily_close 會有 miss 現象, 而是所有程式隨機性的都有 miss 現象, 也就是說, GAE 的 cron 都很忠實地產生 trigger, 但 PHP 主機可能出問題 (DOWN), 導致 PHP 應用程式執行失敗, 所以 cron_log 資料表就不會記錄執行結果.
去看 GAE 的 Logs 便能找出端睨, 例如執行成功的 Logs 回應紀錄如下 :

2013-07-09 17:11:14.469 /fetch_yahoo_dividend 200 34936ms 2kb AppEngine-Google; (+http://code.google.com/appengine)0.1.0.1 - - [09/Jul/2013:17:11:14 -0700] "GET /fetch_yahoo_dividend HTTP/1.1" 200 2961 - "AppEngine-Google; (+http://code.google.com/appengine)" "twstockbot.appspot.com" ms=34937 cpu_ms=0 cpm_usd=0.000351 queue_name=__cron task_name=174a7b46e620a5733ceebdfa6942bc20 app_engine_release=1.8.1 instance=00c61b117c99b5aaefeb1058c41861042bf0ce30

而執行失敗的 Logs 回應紀錄觀察到有兩種, 第一種雖然回應 200, 但是實際上 PHP 程式並未正常執行完畢 :

2013-07-09 16:39:11.898 /fetch_2330_tw_basic 200 2792ms 0kb AppEngine-Google; (+http://code.google.com/appengine)0.1.0.1 - - [09/Jul/2013:16:39:11 -0700] "GET /fetch_2330_tw_basic HTTP/1.1" 200 85 - "AppEngine-Google; (+http://code.google.com/appengine)" "twstockbot.appspot.com" ms=2792 cpu_ms=0 cpm_usd=0.000049 queue_name=__cron task_name=7fccf1fc3674ba5c904a796665b90e9f app_engine_release=1.8.1 instance=00c61b117c99b5aaefeb1058c41861042bf0ce30

第二種失敗例子就是回應 500 (伺服器內部錯誤) :

2013-07-09 16:15:08.646 /fetch_2330_tw_basic 500 3051ms 2kb AppEngine-Google; (+http://code.google.com/appengine)0.1.0.1 - - [09/Jul/2013:16:15:08 -0700] "GET /fetch_2330_tw_basic HTTP/1.1" 500 2313 - "AppEngine-Google; (+http://code.google.com/appengine)" "twstockbot.appspot.com" ms=3051 cpu_ms=0 cpm_usd=0.000264 queue_name=__cron task_name=7fccf1fc3674ba5c904a796665b90e9f app_engine_release=1.8.1 instance=00c61b117c99b5aaefeb1058c41861042bf0ce30

其他觀察結果摘要如下 :

200 34936ms 2kb ms=34937 cpu_ms=0 cpm_usd=0.000351  OK
200 1708ms 0kb ms=1708 cpu_ms=0 cpm_usd=0.000115 OK
200 2792ms 0kb ms=2792 cpu_ms=0 cpm_usd=0.00004 NG
200 192ms 0kb ms=192 cpu_ms=22 cpm_usd=0.000031 NG
200 2792ms 0kb ms=2792 cpu_ms=0 cpm_usd=0.000049 NG
200 88ms 0kb  ms=88 cpu_ms=0 cpm_usd=0.000031 NG
500 3051ms 2kb ms=3051 cpu_ms=0 cpm_usd=0.000264 NG
200 275ms 0kb ms=275 cpu_ms=0 cpm_usd=0.000029 NG
200 87ms 0kb ms=88 cpu_ms=0 cpm_usd=0.000031 NG
200 1821ms 0kb ms=1821 cpu_ms=0 cpm_usd=0.000115 OK
200 101ms 0kb ms=101 cpu_ms=22 cpm_usd=0.000031 NG

歸納上面結果可知, 觀察重點在於三個 : 回應碼 (200?), 資料量 (0KB?), 以及 cpm_used, 因為每一個應用程式都會吐出資料 (我的都是 1, 2KB), 所以不應該 0KB, 如果不是 0KB, 而且 cpm_used>0.000100, 那麼就是成功的; 否則就是失敗的. 若回應 200 且資料量為 2KB, 最後的觀察關鍵在 cpm_used, 失敗的範例通常都是 0.000031, 最大有 0.000049, 沒看到有大於 0.000100 的失敗例子.

我想這就是免費主機的特徵, 也就是他不保證 99.9% 的穩定性, 偶而會 DOWN 個半小時一小時的, 或許只有 80% 也說不定. 解決之道就是用人海戰術, GAE 的 Cron 不要用指定時間 (every day 15:00), 要改成週期性的 every 1 hours 或 every 60 minutes.

以下這一篇是關於 GAE log 的解密, 值得參考 :
Demystifying the App Engine request logs

2013年7月8日 星期一

停止 GAE 的 cron jobs 的方法

今天整理 webabc*** 的 GAE 應用服務, 其中 gaebuilder 是 2011 年所建, 用來驅動 http://tony1966.site11.com 下的應用程式, 但那個網站不能用了, 所以 GAE 的 cron 必須要停掉.
首先跳到 gaebuilder 專案上一層目錄, 用 appcfg 下載整個 APP :
   
 appcfg.py --no_cookies download_app -A gaebuilder -V 1 d:\gae\gaebuilder  

然後將 cron.yaml 備份為 cron_old.yaml, 再把 cron.yaml 刪到只剩第一行 :

cron: 

在 gaebuilder 專案上一層目錄用下列指令更新 cron.yaml 檔就可以清除此 APP 的所有 cron jobs 了 :

appcfg.py --no_cookies update_cron gaebuilder

再用下列指令檢查是否已真的更新 :

appcfg.py --no_cookies cron_info gaebuilder  


2013年7月6日 星期六

GAE 的時區問題

今天被 GAE 的時區搞得七暈八素, GAE 送出的郵件主旨裡, 用 today 紀錄的時間都不對, 慢 8 個小時, 現在是下午 4 點 33 分, 但 GAE 卻顯示 "2013-07-06 08:33:23". 查了一下才知 GAE 用的是 UTC 時間, 所以台北時間 HOUR 要加 8. 因為以前沒用到 GAE 的 datetime, date 等模組, 加上 Python 又不熟, 所以很頭痛.
根據這篇 "Python - Timezones" 說明, 我在 main.py 中加上 :

os.environ['TZ']='Asia/Taipei'
time.tzset()
subject=str(today) + " 盤後分析報告"

時區是設定進去了沒錯 (輸出 os.environ['TZ'] 有顯示 'Asia/Taipei'), 但是時間還是一樣 UTC. Why? 原因在 GAE 的這篇 "類型和 Property 類別" 有說明 :

"部分程式庫使用 TZ 環境變數來控制套用至日期時間值的時區。「應用服務引擎」將此環境變數設定為 "UTC"。 請注意,在應用程式中變更此值,不會變更某些日期時間函式的行為,因為在 Python 程式碼以外的範圍,看不到環境變數的變更"

也就是說, 這一招在 GAE 沒有作用. 
最後在 JiunJuin 君這篇 "[GAE] 時區設定 Asia/Taipei" Brian 的 "在 GAE 使用台灣時區", 與 memo 君的 "GAE 時區" 找到解法了, 原來如此, 呵呵.

from datetime import timedelta, datetime
taipei_time=datetime.now() + timedelta(hours=+8)
taipei_time=taipei_time.strftime('%F %T')
subject=taipei_time + " 盤後分析報告"

這樣郵件主旨就正確顯示 "2013-07-07 15:15:00 盤後分析報告" 啦. 這裏使用了 datetime 模組的 strftime() 方法, %F 表示以 YYYY-MM-DD 顯示日期, 而 %T 則以 HH:mm:SS 顯示時間, 中間用一空格隔開. 呵呵, 我的 Python 太弱了, 要找時間把常用的模組好好測試一番.

參考 :
Time zones in Google App Engine
Time access and conversions

靈糧堂烏克麗麗

今天靈糧堂烏克麗麗班開課,菁菁似乎很期待。楊老師的課很棒,去年暑假我也去跟他學吉他,從和弦開始教,三個禮拜我就會彈了,可惜我太忙,沒時間繼續學。

2013年7月5日 星期五

如何讓網頁不會被 cache

六月底修改了 stockbot 的每日報表產生程式後, 報表一直無法順利產生, 檢查了一陣子也看不出哪裡出錯. 今天去黎陽時帶了小筆電去, 仔細測試一番, 發現是 create_report.php 這程式若由 GAE 去觸發, 即使程式改了, 顯示網頁都不變, 相反的, 若直接改 GAE 程式的 router, 讓 create_report 實質上去觸發別的程式就正常, 顯然是 create_report.php 這程式被 cache 了. 名字改為 create_daily.report.php 就正常, 但下一次觸發又不正常了. 所以要想辦法讓這程式徹底不會被 cache. 我在網路上找到下列兩個資訊 :

  1. Using <meta> tags to turn off caching in all browsers?
  2. http://bbs.csdn.net/topics/40089048

得知要禁止瀏覽器 cache, 必須在 header 中加入 :

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="expires" content="-1">
</head>

content="-1" 表示此網頁永遠都不要 cache.

2013年7月3日 星期三

在 ASP 中使用 ADODB.Stream 上傳檔案問題

最近解決了 ASP 檔案上傳問題, 我想應該記一下, 免得忘了. 幾個月前同事反映, 我的工作日誌系統無法上傳檔案了, 因為剛好部分電腦升級到 IE8, 粗略測試發現用 IE8 上傳失敗, 所以誤以為是 IE8 的問題. 但我還在忙新專案, 沒空研究, 一直拖到上周, 新專案也要用到檔案上傳, 發現 IE6 也不行, 我想該不會是 IIS 伺服器本身吧? 加上最近新增應用程式時失敗, 我就懷疑 FSO 是否被關閉, 所以箭頭就指向伺服器, 由於我使用 ADODB.Stream 物件上傳檔案, 於是上網找了一下資料如下 :


我就聯想到, 該不會是上回 MIS 把伺服器從 Window 2000 Server 升級, 沒把 FSO 與 ADODB.Stream 打開吧? (這要手動啟動服務), 於是趕緊請 MIS 照說明啟動, 

  1. 首先打開 DOS 視窗, 切到 C:\Windows\system32 底下, 執行 :
    regsvr32.exe scrrun.dll
  2. 切換到 C:\Program Files\Common Files\System\ado 下, 執行 :
    regsvr32.exe msado15.dll 
執行這兩個指令後, 都出現 "服務啟動成功", 表示之前這兩個服務都是關閉的. 啟動後檔案上傳服務就恢復正常了.

2013年7月2日 星期二

GAE 的 urlfetch 超時問題

自從使用 GAE 以來, 一直認為其 urlfetch 功能只能執行 5 秒左右, 實際測試就是如此. 例如我們用 Python 去抓取證交所網站之每日收盤行情 :

url="http://www.twse.com.tw/ch/trading/exchange/MI_INDEX/genpage/" + \
      "Report201111/A11220111125ALLBUT0999_1.php?select2=" + \
      "ALLBUT0999&chk_date=100/11/25"
result=urlfetch.fetch(url)

保證在 5 秒後就會看到如下 DeadlineExceededError 錯誤回應 :

"DeadlineExceededError: Deadline exceeded while waiting for HTTP response from URL: http://www.twse.com.tw/ch/trading/exchange/MI_INDEX/genpage/Report201111/A11220111125ALLBUT0999_1.php?select2=ALLBUT0999&chk_date=100/11/25"

這會導致後面的資料分析工作停擺, 所以一直以來我都只用 GAE 的 cron 當 hearbeat 去驅動 PHP 應用程式作網頁擷取與分析的動作. 其實這是我學習 Python 時囫圇吞棗造成的誤解, urlfetch 有一個 deadline 參數可以設定最長的擷取等待時間 (GAE 最長可設為 60 秒, cron 可達 10 分鐘), 如果沒有指定, 那麼在 GAE 預設是大約 5 秒左右, 超過五秒沒有收到回應就會導致 DeadlineExceededError 錯誤. 詳見下列資訊 :

  1. The fetch Function
  2. If Google App Engine cron jobs have a 10 minute limit, then why do I get a DeadlineExceededError after the normal 30 seconds?

所以上面的 Python 程式只要加入 deadline=60 參數就可以避免 5 秒就超時的問題了 :

result=urlfetch.fetch(url, deadline=60)

這樣一來, GAE 的 Cron Jobs 本來顯示 "on time failed" 的 :

every day 15:00 (Asia/Taipei) 
2013/07/02 15:00:00 on time Failed

也變正常了 :

every day 15:00 (Asia/Taipei) 
2013/07/02 15:00:00 on time Success

2013年7月1日 星期一

暑假第一天

阿英這週末帶椏晴來高雄玩,週六我們先去西子灣兜風,再坐渡輪去旗津吃冰,還看到停泊在高雄港的太洋公主號遊輪 (原先以為是麗星郵輪)。
傍晚到夢時代坐摩天輪,開幕到現在我還是第一次來啊!我們來的時間剛剛好, 到最頂端時正好夕陽慢慢沉入海中. 此摩天輪 View 甚好, 可看到整個高雄港. 菁跟椏晴玩水上滾輪玩到欲罷不能!
禮拜天早上太熱,下午才帶她們去糖廠吃冰,逛逛民俗村。


手機上網 WiFi 比行動數據耗電

跟阿英談到手機上網哪一種耗電, 我印象是 WiFi 較省電, 阿英說 WiFi 耗電, 今天上網查了一下, 從這篇 "流言終結者:WiFi真的比3G網絡省電嗎?" 可知, 我錯了, WiFi 比行動上網還耗電. 節錄如下 :

  1. 在開啟了3G網絡並下載互聯網上的內容時我們手機的功耗是會有所提升的,只是提升的幅度並不算明顯。
  2. 3G網絡只有在擁有數據連接的時候才才會產生一定的功耗這樣的設計顯然也是考慮到了對於電池的保護。
  3. WiFi即使在沒有數據傳輸的情況下也會固定的消耗差不多700mW的功耗,從這一點上我們就已經能夠得出在同等的環境下WiFi將會比3G消耗更多。
  4. 當我們下載相應的內容是,CPU的功耗還將同時提高,因此在下載時WiFi所產生的功耗就更是要超過3G的水平了。