2019年8月14日 星期三

C# struct 是傳值(value)還傳參(reference)?為了效能我要加ref嗎?


答案是惱人,是也不是。
利用  「GetType().IsValueType」可以檢查物件是否為「實數型別」。
所以檢測出,struct 物件是實數型別。
但傳遞時,卻不是複製一樣的物件,而是傳參,而這傳參是一種唯讀概念。也就是在函式中改動也不會影響原struct物件的內容。
總之,C#把很多物件都作了優化,把許多類別物件都變成傳參,唯有當你修改時才會複製成新物件。

所以函式的參數如果有struct時,用不用ref效能是差不了太多。反而用了ref很容易一個不小心改了資料還沒發現。如果真的很想知道差異,我作了測試。發現使用ref的效能是好上10%,但這差異是跑了3千萬次後,少了0.29秒。
也就是函式帶struct參數並使用ref,每次可省0.00000967毫秒
結論:函式帶struct參數時,如果不會更動資料,就不要加ref。一來用物理性防呆,二來簡單


函式範例樣子:
使用ref的函式:public string 我的函式(ref 結構資料 A)
未使用ref的函式:public string 我的函式(結構資料 A)






函式
        static public bool 是否為實值型別(object  物件)
        {
            return 物件.GetType().IsValueType;
        }

參考資料
C# 傳值Call by value、參考Call by Reference 與相等比較
[C#][筆記] Value Type (實值型別) vs. Reference Type (參考型別)
作法:了解傳遞結構和傳遞類別參考給方法之間的差異
[沒有蠢問題] c# 如何分辨 實值型別,參考型別
Type.IsValueType Property

2019年8月6日 星期二

Try Catch 效能耗損測試

總結:
直接說結果,是有差別。證明try是會額外耗損資源。多少呢?少到你不會在乎,9億次只額外耗損不到19秒。平均使用一個try額外耗損0.000021毫秒(條件:未觸發catch)
建議:程式不要當機(crash)才是最重要的事,所以別因微不足道的耗損而刻意不使用或關閉。
當掉才是最該避免的事


提醒:只要跑進catch(異常發生)就一定會造成顯著的耗損
提外話:在跑程式時,我有發現一個現象,先執行for迴圈的比較吃虧。所以測試時我有作對調,外加Release+Debug版。所以執行四次。

說明:
執行次數:各自執行9000000*100=9億次
時間單位毫秒


  使用try 未使用try
測試1 6225 620
測試2 10228 6120
測試3 6173 624
測試4 9908 6673
     
加總 32534 14037

記錄圖:
看不懂很正常,因為只是給我自己作記錄用。







程式碼:
        private void 測試()
        {
            long T = 0;
            long T2 = 0;
            int A = 0;
            string B = "";
            System.Diagnostics.Stopwatch sw;
            System.Threading.Thread.Sleep(2000);
            for (int g = 1; g < 100; g++)
            {
                //無try
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                        A = i % 13;
                        A += 1;
                }
                sw.Stop();
                T2 += sw.ElapsedMilliseconds;
                //有try
                System.Threading.Thread.Sleep(1000);
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                    try
                    {
                        A = i % 13;
                        A += 1;
                    }
                    catch (Exception ex)
                    {
                        B = ex.Message;
                    }
                }
                sw.Stop();
                T += sw.ElapsedMilliseconds;
            }
            System.Threading.Thread.Sleep(1000);
            for (int g = 1; g < 100; g++)
            {
                //有try
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                    try
                    {
                        A = i % 13;
                        A += 1;
                    }
                    catch (Exception ex)
                    {
                        B = ex.Message;
                    }
                }
                sw.Stop();
                T += sw.ElapsedMilliseconds;
                //無try
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                    A = i % 13;
                    A += 1;
                }
                sw.Stop();
                T2 += sw.ElapsedMilliseconds;

            }
            txtMsg.AppendText(Environment.NewLine +"使用Try:" + T.ToString());
            txtMsg.AppendText(Environment.NewLine + "未使用Try:" + T2.ToString());
        }

2019年8月5日 星期一

Visual Studio 自動列出成員,但無法按空白鍵自動帶出成員(反藍條)

導言:
有時寫程式寫一寫,突然visual studio無法使用空白鍵,自動完成成員。你大概知道又不小心按到什麼快捷鍵,但就是找不到關掉的地方。即使重啟VS也無效。真是惱人的方便,造成的不便。

Step 1:檢查自動列出成員功能
工具>選項>文字編輯器>C#>一般>陳述式完成>(勾選)自動列出成員。


Step 2:測試
看能否自動列出,和反藍。
有帶出自動,卻無法沒反藍,所以也就無法用空白鍵自動完成。



Step 3:
上方工具列區>右鍵>(勾選)文字編輯器介面



Step 4:
取消「在建議和標準完成模式之間切換(Crt+Alt+空白鍵)」

Step 5:完成
反藍出現了,代表空白鍵能作用了。


總結:
Visual Studio介面設計不佳,只要一急不小心手滑了一下,就把自動完成功能給關了都不知道。而快捷鍵(Crt+Alt+空白鍵)設定更是惱人,中英文切換不小心按快一點就又不明不白的關掉自動完成功能了。


參考資料:
[Visual Studio]需要手動打開提示碼嗎? 這裡教您如何打開自動列出成員。
Visual Studio 中的 Intellisense

2019年8月1日 星期四

收盤價與結算價不同?

收盤價:是指當日最後一筆的成交價


昨日結算價(報價軟體顯示的昨收):是指昨日最後一分鐘的加權平均數(取整數,捨小數)。


結算價=是指今日最後一分鐘的加權平均數(取整數,捨小數)。

開盤平價點=昨收價=昨日結算價


總結:
報價軟體為了方便,把昨日收盤價直接改成昨日結算價。導致許多程式定義時很亂。最好參照期交所定義的名稱來設定資料庫或程式名稱。


期貨相關名詞

股價指數-期貨
.臺股期貨=大台=TX
.小型臺指期貨=小台=MTX
.電子期貨=電子期=TE
.金融期貨=金融期=TF

股價指數-選擇權
.臺指選擇權=選擇權=TXO

股票期貨
.不是加權指數,是個股。一字之差「價」與「票」。


結算價:一般交易時段收盤前1分鐘內所有交易之成交量加權平均價(大台成交價✖成交量)
最後結算價:結算日收盤前30分鐘內「標的指數」之簡單算數平均數→大盤報價,非大台。


參考
期貨選擇權手冊.pdf




大台(臺股期貨)每日漲停價、跌停價 計算方式

導言:
這題難解之處在「關鍵字」很難找,答案是在《期交所》網站《臺灣證券交易所股價指數期貨契約》。找到「每日結算價」這關鍵字答案就差不多出來了

Step 1:每日結算價
定義:每日結算價原則上採當日一般交易時段收盤前1分鐘內所有交易之成交量加權平均價,若無成交價時,則依本公司「臺灣證券交易所股價指數期貨契約交易規則」訂定之

Step 2: 前30個交易日期貨每筆成交資料
位置:期交所>首頁 > 交易資訊 > 資料下載專區 > 交易資訊 > 期貨 > 前30個交易日期貨每筆成交資料 

提醒:注意下載日期和時間,當日的日盤交易(一般時段)資料要到18:40左右才會產出。如果太早下載會不完整。最佳防呆做法就是次日才下載前一個交易日的資料

Step 3:資料格式
格式:成交日期,商品代號,到期月份(週別),成交時間,成交價格,成交數量(B+S),近月價格,遠月價格,開盤集合競價 

篩出:
成交日期=前一個交易日
商品代號=TX
到期月份=操作的大台契約月份(ex:201908)

注意:有價差交易的資料要剔除

Step 4:昨日結算價
公式:昨日,一般交易時段,收盤前1分鐘內,所有交易之成交量加權平均價。
資料區間取:成交時間 134400~134500
計算方式:
昨日結算價_帶小數=sum(成交價格*成交數量)/成交數量,
昨日結算價=(int)昨日結算價_帶小數→只取整數,小數去除不計也不四捨五入。

提示:我是寫入資料庫去撈,所以才會出現sum()函式。
爭議:四捨五入至小數第二位,是期交所的共識法則。但這邊可能是例外

Step 5:今日漲停價
計算方式:昨日結算價✖1.1,取整數(直接去小數,沒有四捨五入,因為會超過10%。

C#程式碼
        public  int  計算當日價格上限(int 昨日結算價)
        {
            return (int)(昨日結算價 * 1.1);
        }

Step 5:今日跌停價
計算方式:昨日結算價✖0.9+1。(加1才能不會超出-10%。除非常好是整數)
C#程式碼
        public  int 計算當日價格下限_小數2位(double 昨日結算價_帶小數)
        {
            if ((昨日結算價_帶小數 * 0.9)%1)//如果剛好整數,就不用+1了
                return (int)(昨日結算價_帶小數 * 0.9);
            else
                return  (int)(昨日結算價 * 0.9) + 1;
        }

爭議:如果是取小數2位作判斷是否為整數(12345.0089在判斷視同12345)
C#程式碼
        public  int 計算當日價格下限_小數2位(int 昨日結算價)
        {
            //取2位小數作有效值
            int i計算 = (int)((昨日結算價 * 0.9)* 100);
            double d結果 = i計算 / 100.0;
            if (d結果%1)//如果剛好整數,就不用+1了
                return (int)(昨日結算價 * 0.9);
            else
                return  (int)(昨日結算價 * 0.9) + 1;
        }

Step 5:驗證一致《期貨每日交易行情下載
位置:期交所>首頁 > 交易資訊 > 交易資訊 > 期貨 > 期貨每日交易行情下載 
比對:結算價是否與期交所一致。




總結:
期交所的名詞常常跟生活用語不同,像「臺股期貨」一般人不會這樣叫,而用「大台」。而昨日結算價,直覺是昨收價。總之,要找出精確數值比預期的困難許多,每日限制±10%,一句話卻充滿著許多定義不明之處,必須慢慢測試才能與期交所公布的一致。


C# 四捨五入函式
        System.Math.Round(10736.79 , 0, MidpointRounding.AwayFromZero)

參考資料:
臺灣期貨交易所
C# 無條件進位,無條件捨去及四捨五入寫法