在 Fragment 中使用 ViewPager + Fragment

在 Fragment 中如果使用了 ViewPager + Fragment ,會出現第二次進入 Fragment 後,會整個 Fragment 空白的問題。

整個頁面的 Fragment , 我們稱為 ViewPagerFragment

在 ViewPager 中的 Fragment , 我們稱為 PagerItemFragment

那為什麼會出現這個問題呢?

在第一次載入 ViewPagerFragment 時,ViewPagerAdapter 也會載入 PagerItemFragment #1 跟 PagerItemFragment #2 ,

並在離開 ViewPagerFragment 時會執行 3 個 Fragment 的 onDestroyView

而在第二次載入 PageFragment 時,則會只會執行 ViewPagerFragment 的 onCreateView(),但卻不會執行 PagerItemFragment #1 跟 PagerItemFragment #2 的 onCreateView()

怎麼解決這個問題呢?

讓 Android 重新掛載原本的 View

在 ViewPagerFragment 中的 onCreateView() 加上

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Log.d(TAG, "onCreateView");
    if (mView != null) {
        ViewGroup parent = (ViewGroup) mView.getParent();
        if (parent != null) {
            parent.removeView(mView);
        }
        return mView;
    }

    mView = inflater.inflate(R.layout.fragment, false);
    ...
    return mView;
}

參考文章

ViewPager+Fragment第二次进入显示空白

android中viewpager+fragment互相切换出现空白页

[Android] 取得目前正在執行的 Activity

AccessibilityService

AccessibilityService 本來是用來做無障礙APP用的 Service,他可以在其它APP中攔截使用者的行為,並且加入自定的動作進去,通常會加入語音,讓視障者可以透過聲音來了解目前手機的行為。

而在使用者切換 Activity 時,AccessibilityService 就會收到一個類型為 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 的 AccessibilityEvent。

因此就能夠透過這個 event 得知目前的 Activity 名稱。
以下的網址有 Sample Code 可以參考.

參考資料

How to get current foreground activity context in android?
AccessibilityService
AccessibilityEvent

WebRTC 筆記

什麼是 WebRTC?

WebRTC (Web RealTime Communication) 是 HTML5 標準所規範的一個項目,WebRTC 的目標是希望使用者在不需要額外裝設軟體與另外進行設定的情況下,就能進行點對點的視訊或檔案交換。
同時也能讓 Web 開發者可以簡單快速地打造 Realtime 應用的網站。具體 Demo Site 可以看 apprtc.appspot.com

WebRTC 的三個主要功能
MediaStream (aka getUserMedia)
從電腦中的 Camera / Mic 取得影像跟聲音,可以設定影像的解析度、開關影像或聲音,同時搭配其它套件加一些後製。

RTCPeerConnection
在雙方裝置中傳送影像跟畫面,把 MediaStream 取得的影像跟聲音傳給對方。
RTCPeerConnection做了很多事情,包含連接方式的管理(P2P / Relay) 、影像解碼、頻寛管理、傳輸安全。
請參考底下的 WebRTC 流程

RTCDataChannel
透過 RTCPeerConnection 傳送資料

WebRTC 相關名詞
STUN
透過 STUN 取得自己的對外IP,以便進行 P2P 連線

TURN
當無法進行 P2P 連線時,則雙方都連上 Turn Server,由 Turn Server 來幫忙雙方進行溝通

ICE
能檢測出目前網路是否能進行 P2P 連線。

WebRTC Server 由以下幾個部份組成
Room Server 用來管理通訊頻道
Signaling Server 用來協調兩端連線,該使用哪種方式
Turn Server 當兩方無法直接 P2P連線時,用來當作中間者幫忙建立兩端連線的橋樑
Turn Rest API 為了讓 Trun Server 能跟 Room 使用同一套身份驗證來管理 Turn 權限檢查,我們需要幫 Turn Server 建立一組 API ,讓 Turn Server 跟其它 Service 溝通。

WebRTC 流程



WebRTC Server 安裝

環境設定
資料夾:
~/WebRTC : 整個 Server 所使用的資料夾
~/WebRTC/apprtc : Room Server
~/WebRTC/collider_root : Signaling Server


安裝 Google App Engine SDK

$ unzip google_appengine_1.9.38.zip
$ echo "export PATH=$PATH:$PWD/google_appengine" >> ~/.bash_profile
$ source ~/.bash_profile
$ export PATH=$PATH:/path/to/google_appengine/

Make sure Python 2.7 is installed on your machine using the following command
$ /usr/bin/env python -V

安裝 Grunt

$ sudo apt-get install npm
$ sudo apt-get install nodejs-legacy
$ sudo npm -g install grunt-cli

安裝 Room Server

$ cd ~/WebRTC
$ cd apprtc
$ sudo npm install
$ sudo apt-get install python-webtest
$ grunt build —force

# 不知道為什麼沒有 apprtc.debug.js
$ cd ~/WebRTC/apprtc/out/app_engine/js/
$ wget https://apprtc.appspot.com/js/apprtc.debug.js

安裝 Go v.16

$ sudo tar -xvf go1.6.linux-amd64.tar.gz
$ sudo mv go /usr/local
$ echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bash_profile

安裝 Signaling Server

$ cd ~/WebRTC
$ mkdir -p collider_root
$ mkdir collider_root/src
$ echo "export GOPATH=$HOME/WebRTC/collider_root" > ~/.bash_profile
$ ln -s `pwd`/apprtc/src/collider/collider $GOPATH/src/
$ ln -s `pwd`/apprtc/src/collider/collidermain $GOPATH/src/
$ ln -s `pwd`/apprtc/src/collider/collidertest $GOPATH/src/
$ go get collidermain
$ go install collidermain

安裝 Turn Server

$ mkdir ~/WebRTC/coTurn
$ cd ~/WebRTC/coTurn
$ tar xvfz turnserver-4.4.1.2-debian-wheezy-ubuntu-mint-x86-64bits.tar.gz
$ sudo apt-get update
$ sudo apt-get install gdebi-core
$ sudo gdebi coturn*.deb

安裝 Turn Rest API

$ mkdir ~/WebRTC/coTurnRestApi
$ vim ~/WebRTC/coTurnRestApi/coTurn.js

var express = require('express');
var crypto = require('crypto');
var app = express();

var hmac = function(key, content){
    var method = crypto.createHmac('sha1', key);
    method.setEncoding('base64');
    method.write(content);
    method.end();
    return method.read();
};

app.get('/turn', function(req, resp) {

var query = req.query;
var key = '4080218913'; // ?~Y?~G~L?~Z~D key ?~X??~K?~E~H设置好?~Z~D, ?~N?~H??~W??~\~M?~J??~Y??~Z~Dkey?~[??~P~L

if (!query['username']) {
    return resp.send({'error':'AppError', 'message':'Must provide username.'});
} else {
    var time_to_live = 600;
    var timestamp = Math.floor(Date.now() / 1000) + time_to_live;
    var turn_username = timestamp + ':' + query['username'];
    var password = hmac(key, turn_username);

    return resp.send({
        username:turn_username,
        password:password,
        ttl:time_to_live,
        "uris": [
            "turn:192.168.24.163:3478?transport=udp",
            "turn:192.168.24.163:3478?transport=tcp",
            "turn:192.168.24.163:3479?transport=udp",
            "turn:192.168.24.163:3479?transport=tcp"
            ]
    });
}

});

app.listen('8081', function(){
    console.log('server started');
});

$ cd ~/WebRTC/coTurnRestApi
$ npm install express

設定 Turn Server 

$ sudo vim /etc/default/coturn

# TURNSERVER_ENABLED=1 -> TURNSERVER_ENABLED=1

# 產生 SSL 憑證
$ sudo openssl req -x509 -newkey rsa:2048 -keyout /etc/turn_server_pkey.pem -out /etc/turn_server_cert.pem -days 99999 -nodes

$ sudo vim /etc/turnserver.conf

listening-device=eth0
listening-port=3478
listening-ip=192.168.24.164
relay-device=eth0
relay-ip=192.168.24.164
Verbose
fingerprint
lt-cred-mech
use-auth-secret
static-auth-secret=trendtec
realm=trend-tec.com.tw
cert=/etc/turn_server_cert.pem
pkey=/etc/turn_server_pkey.pem

設定 Room Server

# 如果設定該檔案沒作用,試試看設定 ~/WebRTC/apprtc/src/app_engine/constants.py
$ vim  ~/WebRTC/apprtc/out/app_engine/constants.py 

TURN_BASE_URL = 'http://192.168.24.164:8081'
CEOD_KEY = 'trendtec'
WSS_INSTANCES = [{
    WSS_INSTANCE_HOST_KEY: '192.168.24.164:8089',
    WSS_INSTANCE_NAME_KEY: 'wsserver-std',
    WSS_INSTANCE_ZONE_KEY: 'us-central1-a'
}, {
    WSS_INSTANCE_HOST_KEY: '192.168.24.164:8089',
    WSS_INSTANCE_NAME_KEY: 'wsserver-std-2',
    WSS_INSTANCE_ZONE_KEY: 'us-central1-f'
}]

# 可以先不用設定這個,等確定有 ssl 相關的問題再來設定這個
# 如果沒有 https 的話,要修改  ~/WebRTC/apprtc/out/app_engine/apprtc.py

wss_url = 'wss://' + wss_host_port_pair + '/ws’ > wss_url = 'ws://' + wss_host_port_pair + '/ws'
wss_post_url = 'https://' + wss_host_port_pair > wss_post_url = 'http://' + wss_host_port_pair

啓動 coTurn

service coturn start

啓動 Turn Rest Api

$ cd ~/WebRTC/coTurnRestApi
$  node coTurn

啓動 Room Server

$ ~/WebRTC/google_appengine/dev_appserver.py --host=192.168.24.164 ./out/app_engine

啓動 Signaling Server

$GOPATH/bin/collidermain -port=8089 -tls=false -room-server=http://localhost:8080


WebRTC Client


參考文章

AppRTC - Google 提供的 Demo Sample Code

Android Flux

觀念

Dispatcher

讓「有註冊到 Dispatcher 的 Store」都能收到 ActionCreator 發送的 Action。

Action

Action 是一個 Event Object ,用來通知 Store 有新的 Action 並且能識別該 Action 的類型,讓 Store 知道要不要處理收到 Action

ActionCreator

提供一個元件來規範建立 Action 並且傳送給 Dispatcher的機制。

Store

收到 Action 後,進行一些處理,像是更新 db 或是更新 ArrayList,然後再通知 View 更新 UI。

View

整個流程有 2 個地方會使用到 View,就是開頭跟結束的時候。
1. 當 User 操作 View 時,會使用 ActionCreator 建立新的 Action
2. 接受 Store 的通知,事情都處理完了,可以更新 UI 了。

參考資料

AndroidFlux项目一览-Flux架构的Android移植
AndroidFlux-异步请求和网络

macOS (MacOS X) 內建查碼小工具

enter image description here

常常遇到不會打倉頡碼或不會唸的中文字嗎?

Mac有內建一個好用的小工具,可以同時查詢輸入文字的注音,拼音,倉頡碼。
像是遇到不會打倉頡碼的中文字,只要在這個小工具用注音輸入法輸入,馬上就可以查到倉頡碼的打法了,真是超好用 der~
相反也可以用倉頡輪入法去查不會唸的中文字了~

有在用拼音輸入法、注音輸入法、倉頡輸入法、筆畫輸入法的朋友,都推薦使用看看喔!

怎麼開啓小工具?

  • 在選單列上點選輸入法的圖示,然後選擇「尋找輸入碼」。
  • 快速鍵
    – 先切換到中文輸入法
    – 然後同時按下 Shift + Option + L

Whisker股票通

Whisker股市通 Index

Whisker股市通
最近在 Gitbook 看到這本說明股票觀念的書,感覺寫得蠻清楚地!
以下是我個人覺得比較重要的重點與記錄一些自己對於投資的方向。

不過還是建議去直接去看書的內容,或許有什麼新發現。
也觀迎一起討論投資的方向。

股市概念

「牛市」=「多頭」=「漲」

市場常以目前大盤指數在季線之上,且趨勢往上走時,稱為多頭市場 。如果大盤在某個均線譬如季線(60日平均值)「之上」時,表示近一季買進的人,平均是處於賺錢的狀態,這時候樂觀的態度容易持續。

「熊市」=「空頭」=「跌」

如果大盤指數在季線之下,且趨勢往下走時,稱為空頭市場。如果大盤在某個均線譬如季線(60日平均值) 「之下」時,表示近一季買進的人,平均是處於賠錢的狀態,這時候悲觀的態度也容易持續。

成交量

一、 價格上漲,成交量萎縮(價漲量縮)。這情況如果是出現在急速上漲的股票身上,就是「市場惜售」。或者買氣降低,走勢即將翻轉。

二、 價格上漲,成交量擴增(價漲量增)。表示市場很熱,吸引許多買盤,且買和賣雙方「換手」積極,交易熱絡,股價有望持續上揚。

三、 價格下跌,成交量萎縮(價跌量縮)。意味著市場買氣冷清,正在做「探底」的動作,也可能是賣壓消耗殆盡,行情可能反轉。

四、 價格下跌,成交量擴增(價跌量增)。一種情況是停損賣壓殺出,另一種則是股價已經超跌,進而吸引到低接、「抄底」的買盤進場。

加權指數

加權指數是用一個數字代表所有上市股票的漲跌情況總合,但市值較高的股票占較大的加權指數的比例
集中市場加權指數 = (目前總市值/當日基值) × 100
目前總市值=每股股價×總股數

當日基值=前一日的總市值?

權值股

股本較大、市值較高的公司,會被稱為「權值股」,權值股因為占市場之權重比較大,因此,不管這些個股股價上漲還是下跌,對大盤都有很大影響。典型的權值股如台積電、鴻海及中華電

而在權值股中又以台積電最具代表性,因其佔台股總市值高達15%

除權息

除權,是公司將盈餘轉換成股份,按照股東持股比例分給股東,股東持股數增加,公司股本增加

除息,是公司將盈餘以現金的方式按照股東持有股份比例分配現金股利,股東持股數不變,而公司可用現金減少。

OOO公司今年宣布發放現金股利1.5元,股票股利1元。

現金股利1.5元表示每一股配發1.5元,所以當我們持有一張OOO就可以收到1000股×1.5= 1,500元的現金股利

股票股利1元表示每張面額10元的股票配1元的股票,因此當我們持有1000股時便能配到100股的股票股利。

因此我們若參加除權息,我們總計可以得到1500元的現金股利和100股的股票股利。

那到底什麼時候錢買進股票才能參加除權息呢?

因為台灣證券交割採T+2制,在購入後的兩天才會交割,故要在最後過戶日7/14時持有股票的話,最晚必須在7/12購入,也就是除權除息日的前一天,方能參與除權息。

那每間公司的除權息日是什麼時候?

除權息後股價怎麼計算?

如果除權息前一天收盤價是100元,現金股息是2元,股票股利是2.5元,
那除權息參考價=(100−2) / (1+0.25)=78.4元

填權息

以上面同時除權息的例子來說,
若股價從參考價78.4一路漲回100,便是填權息;
若股價由78.4下跌,則是貼權息。

個股概念

持有一家公司的股票後獲利的來源有兩種,一種是當股價上漲時賣出,賺取買賣價差,另一種就是持有股票,拿取來自於公司盈餘所分配的股利。

買進賣出

買進價格,是指投資人委託掛單欲買進該股票時,願意付的「最高」價格。
賣出價格,是指投資人委託掛單欲賣出該股票時,願意賣出的「最低」價格。
其中買進價格一定高於賣出價格,否則在投資人掛單時就會直接成交。
當委買價與委賣價有交集時,交易所就會以「價格優先,同等價格下時間優先的原則」進行撮合,這筆交易就會成交。

最佳五檔買賣價

最佳五檔買賣價是買家出價最高的五檔價位跟張數,以及賣家出價賣出最低的五檔價位跟張數。

內外盤

一筆股票交易之所以成功,都需要買方或賣方其中一方願意「妥協」並迎合對方的報價,也就是說每一個交易都存在著買方或賣方的勝利。
若一筆交易是由「買進價」成交,也就是賣方來主動迎和買方,則被稱作「內盤」,
而若一筆交易是由「賣出價」成交,也就是買方主動去迎和賣方,則被稱作「外盤」。

若投資人認為股票後勢看漲,因此便會急於買進股票,於是便不斷主動迎和賣方的報價,也就造成「外盤成交量」也就是「外盤量」不斷竄升。相反地,若投資人認為股價將走弱,於是便急於出清手上持股,於是便不斷主動迎合買方的報價,也就造成「內盤量」節節攀升。
內盤強勢→賣方氣勢較強,股價後勢看跌。
外盤強勢→買方氣勢較強,股價後勢看漲。

盤後交易

只能以「收盤價」即「最後一筆成交價」下單,只能在下午兩點到兩點半之間下單,兩點半時交易所電腦會自動搓合,隨後顯示是否成交。
每個交易日下午一點半收盤後的下單,若沒有特別標註「盤後」則都算是隔天的預約單喔!所以如果想要在二點進行「盤後交易」,記得不要下錯單了!

漲停跌停

漲停跌停,代表股價在單日的最高漲幅跌幅,是以前一交易日收盤價格做為基準價格,基準價格×1.10是漲停價格,基準價×0.90是跌停價格,也就是說股價一天的漲幅和跌幅最多都是10%。

平盤

前一個交易日的收盤價,就是次一個交易日的開盤參考價,而這個價格就是所謂的「平盤」
若當日收盤價等於前一日收盤價,則稱為收平盤。 平盤價格可以用來判斷股票上漲下跌。如果今天的收盤價格高於平盤價格就是上漲,低於平盤價格就是下跌。

交割

股票交割

假設小明在T日購買一張股票,則要等到T+1日這張股票才會被轉入小明的「證券集保帳戶」,簡言之,小明要在購買股票的隔天才能把股票拿到手,也才能再進一步將其賣出,但若該個股為金管會規定之「可當沖標的」,則可在同一天內進行買賣。可當沖標的清單如下: http://www.twse.com.tw/ch/trading/exchange/TWTB4U/TWTB4U.php

股款交割

同上,假設小明在T日購買一張股票,則小明在T+1日時就能拿到這張股票,那小明需要在什麼時候付款呢?答案是T+2日!也就是若小明今天買股票,只要在後天早上十點前將需付價款存進「證券交割帳戶」即可!

違約交割

如果投資人在進行交易後無法履行交割義務,也就是到T+2日早點十點時帳戶中仍沒有足夠的金額,則證券商可以以成交金額之70%向投資人收取違約金,此外,證券商甚至可以將投資人集保帳戶中的其他股票自行賣出以償還違約債務和費用,且若金額不足,仍得向投資人求償剩餘金額。此外,若投資人違約交割情節重大足以影響市場秩序者,也有可能面臨刑事責任。

手續費、證交稅

買進

付給券商之手續費金額為成交金額的千分之1.425,亦即買一張100元的股票需付給券商100×1000×0.1425%=142.5元

賣出

再付一次手續費給券商,即成交金額的千分之1.425,另外還要繳交成交金額千分之三的證交稅給政府。亦即賣一張100的股票需付給券商142.5元加上100×1000×0.3%=300元的證交稅,總共442.5元

由此可見,若買一檔股票想要賺錢,則投資報酬率須超過0.6%以上才行,先算附加成本為「股價×0.6%」為股價外的成本,若上漲幅度超過額外成本方為開始賺錢。

小明買進一檔市值10元股票,則投資額外成本為10×1000×0.6%=60元,也就是此檔股票必須超過約10.06元,小明在此時賣出此檔股票才有獲利。

若手續費不足20元將以20元計

選擇個股

一般而言,與股票相關的知識與選股策略可大致分為「基本面」、「技術面」、「籌碼面」、「消息面」

基本面

營收

雖然稅後盈餘才是公司真正的獲利,但稅後盈餘只會在每季公布的財報上顯示。投資人每三個月才能知道公司的營運狀況,沒有辦法辦法即時地反映在投資策略上。於是政府規定,公開發行公司每個月10號前要公布上個月的營收,讓投資人能夠取得每個月的最新資訊,有助於決定是否要買入或賣出股票。
營收年增率:(105年1月營收-104年1月營收) / 104年1月營收 x 100%
營收月增率:(105年1月營收-104年12月營收) / 104年12月營收 x 100%

EPS

EPS(Earnings Per Share,每股盈餘)是公司的獲利指標,衡量一年中公司為每一股股票賺到了多少錢。
EPS = 稅後淨利 / 股本數

本益比

所謂的「本」是股票的每股價格,「益」是公司一年的每股稅後盈餘(EPS)。本益比是指投資人對每一元盈餘所願意付出的價格,也就是投資者為獲得一元的利潤,所要投資的金額。
本益比=每一股股價/每一股淨利=每一股股價/EPS

用本益比選股時,可以和同產業的公司做比較。比如說,IC設計公司的本益比通常都超過20倍,如果有這產業的公司本益比只有15,而且其他指標(營收、毛利率等等)都在成長,那可能代表該公司的股票價值被低估,或許可以考慮買進。

ROC

ROE又稱股東權益報酬率,是公司拿股東的錢去投資、營運獲利的報酬率,衡量的是公司替股東賺錢的效率,數值越高,代表公司利用股東權益創造獲利的能力越好。
ROE=稅後純益/股東權益

「股東權益」更進一步包含了特別股和保留盈餘。所以股東權益是什麼?

ROE的高低也會因為行業類型而不同。不需要太多資產投入的行業,例如諮詢公司,通常ROE會較高;需要大量投入的行業,比如說煉油廠,ROE通常較低。所以不能單以ROE判斷公司的盈利能力,應用相同產業來做比較。
要從ROE選股的話,必須觀察長期的趨勢,是否能維持在一定的水準。通常會以最近10年ROE>8%、最近3年ROE>15%作為選股標準。

ROA

ROA又稱資產報酬率,衡量的則是公司之資產是否充份利用,和ROE類似的是,ROA越高也代表著公司每一塊錢的資產可以創造更多獲利。但ROA多考慮了從負債帶來的效益,因此常用於分析銀行和金控公司等負債比例高的行業。銀行存款、向同業和政府拆款和舉債都是金控公司的負債,雖然他們負債比率極高,但並不代表他們的經營狀況不穩定。
用ROA選股時,也應注意該公司ROA是否持續穩定地持平或上升,通常會和同業做比較,或是以近三年ROA>8%且有穩定上升作為選股條件。

技術面

K棒

K棒 Candlestick
紅色K棒又稱為「陽線」代表收盤價高於開盤價,白色或綠色K棒又稱「陰線」,代表收盤價低於開盤價,至於「影線」部分的頂端則為當日最高價,底端則為當日最低價,K棒實體上方的引線稱為「上影線」、實體下方的引線稱為「下影線」。

而「K棒」本身的紅綠則只關乎當日的「收盤價是否高於開盤價」。例如上圖黃色圈圈處的第二根K棒,雖然當天K棒呈現白色、綠色(即收綠K),但由於收盤價大於前一天之收盤價,因此股價仍為上漲,但K線為白色(綠色)。

強勢K棒

強勢K棒
「強勢紅棒」及「強勢黑棒」無上下影線,也就是說「強勢紅棒」的開盤價即最低價,收盤價即最高價,代表股價開最低、收最高,當日漲勢十分強烈。而強勢黑棒的開盤價即最高價,收盤價即最低價,代表股價開最高、收最低,當日跌幅十分可觀。

長上下影線

長上下影線
當上影線或下影線長度較長,甚至遠長於K線「實體」部分時,投資人就必須特別注意了!因為這可能代表該日有強勢買壓或賣壓,將可能影響未來股價走勢。若K棒在收盤後留下「長下影線」的話,代表收盤價和最低價中間有一段很長的差距,則可能是股價跌深後反彈強勢,底部有穩固支撐,未來股價可能走高或持續盤整,如圖〈一〉。而若K棒在收盤後留下「長上影線」的話,代表最高價和收盤價中間有一段很長的差距,則可能是股價漲多後往下修正,頭部有停利賣壓,未來股價可能走跌或持續盤整,如圖〈二〉。
長上影線 → 漲多後,頭部有難以突破之賣壓,未來股價可能盤整或走跌。
長下影線 → 跌深後,底部有難以跌破之支撐,未來股價可能盤整或反彈。

十字線

十字線
當上下影線長度相當,且K線實體部分「極短」而形成一個形狀像十字般的K線時,我們將其稱為「十字線」。十字線的特點在於開盤價、收盤價幾乎相等,因此實體部分幾乎為一直線,而最高價和最低價差距大,因此收盤時留下長度可觀且相近的上下影線。
十字線的意義在於多空交戰激烈,因此後勢難以判斷,保守的作法是暫且觀望,待兩三日後若股價漲跌趨勢明顯再行交易

籌碼面

三大法人

股市籌碼面的重點在於分析大戶動向,因為其雄厚資金具有影響股價的能力,因此若散戶能夠抓準大戶的進出場時機,則可以搭順風車賺取一筆豐厚的利差。

市場上主要的大戶分為三種人:

  • 一、三大法人(外資、自營商、投信)
  • 二、關鍵內部人(掌握內部關鍵消息的人,如董事監事)
  • 三、大股東(持有大量該公司股票的股東)

外資

外資持有台灣股票近35%,根據統計,外資只要買超台股 (買進金額大於賣出金額) ,大盤 (所有上市公司市值加權平均) 就有七成機率會上漲,以下介紹外資主要操作手法:

- 一、買大牌 (偏重權值股) 外資去全球股市搜刮權值股 (價格高且發行張數多、大型企業)
- 二、買優良股 (重視基本面,不重視股價) 因為資金龐大,如果交易一出手就漲停跌停的小股票沒有意義,因此他們找出基本面良好的公司,不論股價高低,直到基本面出現變化。

台灣指數期貨

「台指期貨」是台灣期貨交易所推出的產品,屬於期貨的一種,它的標的是依據台灣的股票集中市場之加權指數去做漲跌變動

假設小明預期大盤即將上漲而買進一口大台指期,若隔日大盤上漲一百點,則小明獲利100×200=20000元,而若大盤下跌150點,則小明虧損150×200=30000元,需要補繳64000−(83000−30000)=11000元之保證金

台灣指數期貨對大盤走勢而言有著重大影響,投資人必須密切關注並審慎應用,因期貨通常是現貨走勢的領先指標,因此投資人可藉由期貨走勢來了解市場的多空氣氛,以預判未來大盤走勢,並且透過長握大盤走勢來擬定選股策略。

RxJava

什麼是 RxJava?

a library for composing asynchronous and event-based programs by using observable sequences.

從 RxJava Github 的介紹,可以很清楚地知道 RxJava 的用途是什麼。
一個利用 Observable Sequences 來達成「非同步」與「事件導向」設計的套件。
先來簡單描述一下 Observable Sequences、非同步、事件導向,這三個專有名詞。

Observable Sequence

首先要先了解什麼是 Observable Pattern(觀察者模式) ,就像我們平常燒開水一樣,打水壺放上瓦斯爐後,我們就會先去做其它事情,等水滾的時候水壺在叫了,才會再回去火關掉,拿煮好的水去使用。

以下的程式是表達人與水壺的關係,重點在於人並沒有一直去檢查水滾了沒有,而是水滾的時候,水壺會自動跟人產生互動。

這就是 Observable Pattern(觀察者模式)。

class Jug {
    private Human mHuman;

    // 加入要通知的人
    public void add(Human human) {
	    this.mHuman = human;
    }

    // 水滾了
    public void fired() {
        this.mHuman.listened();
    }
}

class Human {
    // 有沒有聽到水滾了
    public void listened() {
        System.out.print("可以洗澡了!!!");
    }
}

Jug jug = new Jub();
Human human = new Human();
jug.add(human);
jug.fired(); // 這時 Human 就知道可以洗澡了!

而 Observable Sequence 的意思就是把我們在寫的程式流程轉化成 Observable Pattern。

非同步

非同步其實是 Observable Pattern 的一個特性,是表示人不用一直在停留在「等水滾,然後去洗澡」的狀態,他可以先去做「別的事情」,等「水滾了」就「可以去洗澡」。
非同步的意思就是「人」跟「水壺」的狀態是處於沒有相關性的情況,可以各自去做自己的事情。

事件導向

事件導向也是 Observable Pattern 的一個特性,因為「人」跟「水壺」的狀態是處於沒有相關性的情況,那到底什麼時候「人」跟「水壺」又開始產生影響了,就是「事件」發生的時候,「水滾了」之後,「人就會聽到」,然後「人就可以去洗澡了」。

為什麼要用 RxJava?

所以 RxJava 就是把你的程式流程做了一些改變,改變成「非同步」與「事件導向」。

那做了這些改變的好處是什麼呢?

當你需要做一些要花一些時間的事情時,不會讓使用者的操作卡在 Loading 的畫面,可以讓使用者先進行其它的操作,當事情作完的時候,再通知使用者讓他能夠進行原本的操作。

其實在使用 RxJava 之前,大家應該都有做過類似的事情,只是使用的方法不一樣。
像是「建立 Thread 來處理事情」,「使用 AsyncTask」,「Handler的postDelayed」,在理論上都是同樣的東西。

那什麼還要使用 RxJava 呢?

懶啊!!!!!

懶得去建立 Thread , 懶得去 new AsyncTask , 還要去 try-catch 抓 exception , 一下要轉到 uiThread , 一下又要轉到 workThread , 煩不煩啊!!!!
更不要說還有不同 AsyncTask 的 doBackground 都跑在同一個 Thread 上,會彼此卡住的同題要處理。

RxJava提供更簡單的方式(?,其實這個看個人),來幫你把這些雜七雜八的事情處理掉。讓你可以更專心地寫你要的功能。

RxJava 怎麼用?

重點就是這個了,好用才要用,不好用就乖乖回去用 Handler / AsyncTask …
在 Github 中 RxJava 提供了很多 method 可以用,但是一般使用上,大部份都是以切換 Thread 跟 轉換資料型態為主,所以會以這個部份做說明。

Hello World!

如果把上面的「水滾了」的程式改成 RxJava 應該會是以下這樣(程式有一點點差異,不過不影響要表達的意思)

Subscriber<String> human = new Subscriber<String>() {
    @Override
    public void onCompleted() {

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onNext(String message) {
        Log.i(TAG, message);
        if (message.contains("水滾了")) {
            Log.i(TAG, "可以洗澡了!!!");
        }
    }
};

Observable<String> jug = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("60度了");
        subscriber.onNext("70度了");
        subscriber.onNext("80度了");
        subscriber.onNext("90度了");
        subscriber.onNext("100度水滾了!!!!");
    }
});

jug.subscribe(human);

不過以 RxJava 的寫法,通常會建議改成 Chain 的寫法會更簡潔清楚

Observable.just("60度了", "70度了", "80度了", "90度了", "100度水滾了!!!!")
    .subscribe(new Action1<String>() {
        @Override
        public void call(String message) {
            Log.i(TAG, message);
            if (message.contains("水滾了")) {
                Log.i(TAG, "可以洗澡了!!!");
            }
        }
    });

這樣就是「水滾了」的 RxJava 版本了。

切換 Thread

不過剛剛寫好的「水滾了」,其實並沒有「非同步」的特性。

因為「人」與「水壺」都在同一個 Thread 底下工作,所以「水壺」在「滾水」的時候,「人」其實不能去做其它事情。

因此我們需要把「人」與「水壺」放到不同的 Thread 底下工作,才能達到「非同步」的效果。
這也是 RxJava 被人推薦的原因,要做到這件事,只要加入短短 2 行 code 就完成了,如果是使用「AsyncTask」或「Handler」,大概都要重新順一次流程了。

以下是把「水壺」放到 IO Thread,「人」放到 UI Thread 的版本

Observable.just("60度了", "70度了", "80度了", "90度了", "100度水滾了!!!!")
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<String>() {
        @Override
        public void call(String message) {
            Log.i(TAG, message);
            if (message.contains("水滾了")) {
                Log.i(TAG, "可以洗澡了!!!");
            }
        }
    });

轉換資料型態

有時候就是這樣,程式都寫好了,才發現需求有修改,或是文件有錯,本來以為應該是拿到 String ,結果郤是拿到 Integer ,難道程式又要重寫了嗎?

這也是 RxJava 好用的原因,對於修改原本的程式相對好改許多,把每個動作都仔細的切成一個 method ,再像堆積木一樣,積成一個流程。

Observable.just(60, 70, 80, 90, 100)
    .map(new Func1<Integer, String>() {
        @Override
        public String call(Integer temperature) {
            return (temperature == 100) ? "100度水滾了!!!!" : temperature + "度了";
        }
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<String>() {
        @Override
        public void call(String message) {
            Log.i(TAG, message);
            if (message.contains("水滾了")) {
                Log.i(TAG, "可以洗澡了!!!");
            }
        }
    });

過濾資料

再次遇到需求調整,希望80度以上再跟「人」通知就好了!
沒問題,還好我有用 RxJava !

Observable.just(60, 70, 80, 90, 100)
    .filter(new Func1<Integer, Boolean>() {
        @Override
        public Boolean call(Integer integer) {
            return (integer > 80);
        }
    })
    .map(new Func1<Integer, String>() {
        @Override
        public String call(Integer temperature) {
            return (temperature == 100) ? "100度水滾了!!!!" : temperature + "度了";
        }
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<String>() {
        @Override
        public void call(String message) {
            Log.i(TAG, message);
            if (message.contains("水滾了")) {
                Log.i(TAG, "可以洗澡了!!!");
            }
        }
    });

加個 filter 就搞定了,是不是真的還好有用 RxJava … XD

結論

RxJava 的功能還很多,感覺 RxJava 無比強大,好像幾乎可以改變原本寫程式的觀念。
這種感覺,在學 Node.js® 的時候也有過一次,就連 PHP 也開始有 ReactPHP 了。

現在 Realtime 的系統越來越常見了,或許接下來會開始越來越接觸到這種 Reactive 的寫法,自己寫程式的邏輯也要再重新適應一次了。


參考網頁

RxJava Github Project Page
给 Android 开发者的 RxJava 详解
RxJava@Open Android