嗚嗚喔學習筆記

搜尋此網誌

2025年6月6日 星期五

你真的知道自己投入股市多少錢嗎?用 Python 還原「真實資金」的方法大公開

還原你真正投入股市的資金

💰 用 Python 還原「到底花了多少錢買股票?」

有時候你會問自己:

「我帳上股票價值是這樣沒錯…但我到底實際投入了多少錢?」

這問題乍聽簡單,其實非常常見也非常棘手。


🧨 問題:我錢早就滾來滾去了啊!

很多人投資時:

  • 沒記自己加碼多少錢(沒有入金記錄)
  • 只剩券商提供的「買賣交易紀錄」

但這樣會出現什麼狀況?

  • 你賣出股票,帳戶有現金
  • 過幾天再買別的股票,用的是原本賣出的錢
  • 重複買賣幾次後,你總買入金額可能膨脹了兩倍!

✅ 所以不能單看「買進總額」或「-帳面淨流出」來當作你的投入資金


✅ 解法:模擬帳戶現金流,還原真實加碼金額

💡 核心邏輯:

  1. 把交易紀錄照時間排序
  2. 模擬一個帳戶現金餘額(初始 0)
  3. 遇到賣出(+金額):錢進帳戶
  4. 遇到買進(-金額):
    • 有現金就扣
    • 不夠的話,補上缺口 → 這才是真的你「掏口袋的錢」

🧮 舉個例子

1月 買 -10,000 現金 = 0 → 實際投入 10,000
2月 賣 +12,000 現金 = 12,000
3月 買 -18,000 現金不足,補 6,000 → 再投入 6,000

✅ 結論:實際總投入是 16,000

不是你以為的「買了 28,000 就是投入 28,000」


🛠️ Python 程式碼怎麼寫?


account_cash = 0
net_invested = 0

for row in sorted_transactions:
    amt = row["Amount"]
    if amt > 0:  # 賣出
        account_cash += amt
    else:        # 買入
        needed = -amt
        if account_cash >= needed:
            account_cash -= needed
        else:
            net_invested += (needed - account_cash)
            account_cash = 0

📈 實際用途

  • 想算報酬率,但沒記入金
  • 有做再平衡、滾動買賣的交易人
  • 想看 Sharpe Ratio / IRR 時,不想被「假投入」影響

🔚 小結

這個「還原現金投入」的方法非常簡單但非常實用。
比起只看總買進金額,它能更貼近你真正「從錢包拿出來」的資金。

把它寫進你的投資分析程式,或記帳工具裡面,你會對自己的績效有更真實的掌握 👌


(想要這段程式變成一個 pandas 函式或封裝工具?可以留言或私訊我 🙌)

2025年1月16日 星期四

PS Blending Modes (常用混合公式整理)

 以下內容整理自您提供的圖片,主要是各種「混合模式 (Blending Modes)」對應的運算公式。為方便閱讀,我將其歸納成表格形式,並依常見的 Photoshop/繪圖軟體混合模式命名進行分類。若有些名稱與您日常使用的軟體不同,請自行對照調整。


1. 基本比較類 (Darken / Lighten)

模式名 公式 說明
變暗 (Darken) C=min(A,B)C = \min(A, B) 在每個像素比較兩圖層亮度,取較暗者為結果
變亮 (Lighten) C=max(A,B)C = \max(A, B) 在每個像素比較兩圖層亮度,取較亮者為結果

2. 乘法 / 反向運算類 (Multiply / Screen / 相關衍生)

模式名 公式 說明
正片疊底(Multiply) C=A×B255C = \dfrac{A \times B}{255} 兩圖層相乘後再除以 255,結果通常比原圖更暗
濾色(Screen) C=255(255A)×(255B)255C = 255 - \dfrac{(255 - A) \times (255 - B)}{255} 先將兩圖層反相,再進行乘法,最後再反相,結果通常比原圖更亮
線性加深(Linear Burn) C=A+B255C = A + B - 255(若小於 0 則視作 0) 簡單的線性運算,使結果變暗
線性減淡(Linear Dodge) C=A+BC = A + B(若大於 255 則視作 255) 簡單的線性運算,使結果變亮
顏色加深(Color Burn) C=255(255A)×255BC = 255 - \dfrac{(255 - A) \times 255}{B}(常見定義之一) 透過對亮部的「壓暗」達到加深效果,實作可能略有差異
顏色減淡(Color Dodge) C=A×255255BC = \dfrac{A \times 255}{255 - B}(常見定義之一) 透過對暗部的「提亮」達到減淡效果,實作可能略有差異

註:有關「顏色加深 / 顏色減淡」的公式,在不同軟體或文檔中可能會有些微差異,以上為常見版本參考。


3. 疊加 / 光系混合 (Overlay / Hard Light / Soft Light / Vivid Light 等)

這一類混合模式通常會先判斷 B(上層) 的亮度是否大於或小於中間值 (128),再採用不同公式,使暗部和亮部各自以不同方式混合。

3.1 疊加(Overlay)

通常定義如下(此處以 128 為分界):

  • B128B \le 128C=A×B128 C = \dfrac{A \times B}{128}
  • B>128B > 128C=255(255A)(255B)128 C = 255 - \dfrac{(255 - A)(255 - B)}{128}

3.2 強光(Hard Light)

「強光」與「疊加」雷同,但視角不同(以 B 為基準)。常見定義為:

  • B128B \le 128C=A×B128 C = \dfrac{A \times B}{128}
  • B>128B > 128C=255(255A)(255B)128 C = 255 - \dfrac{(255 - A) (255 - B)}{128}

註:某些資源中,強光(Hard Light) 也會寫成以上 Overlay 互換的形式,請依軟體實際實作為主。

3.3 柔光(Soft Light)

柔光的公式實作比較多樣,常見的 Photoshop 版本定義(以下僅作參考):

  • B128B \le 128C=A×(B+128)255 C = \dfrac{A \times (B + 128)}{255}
  • B>128B > 128C=255(255A)(255B)255 C = 255 - \dfrac{(255 - A)(255 - B)}{255}

不同軟體對「柔光」的實作公式也可能不同,主要是為了產生更柔和的光影過渡。

3.4 亮光(Vivid Light)、線性光(Linear Light)、點光(Pin Light) 等

  • 亮光(Vivid Light)
    結合了「顏色加深 / 顏色減淡」的概念:

    {B128:C=255(255A)×128BB>128:C=A×128255(B128) \begin{cases} B \le 128: & C = 255 - \dfrac{(255 - A)\times 128}{B} \\ B > 128: & C = \dfrac{A \times 128}{255 - (B - 128)} \end{cases}

    (此為參考公式,實際實作可能有所調整。)

  • 線性光(Linear Light)
    常見定義:

    C=A+2B255 C = A + 2B - 255

    (暗部時像線性加深,亮部時像線性減淡。)

  • 點光(Pin Light)
    簡化來說,會將亮部與暗部門檻化,以保留部分像素原值、部分取另一圖層值。常見寫法:

    {B128:C=min(A,2B)B>128:C=max(A,2B255) \begin{cases} B \le 128: & C = \min(A, 2B) \\ B > 128 : & C = \max(A, 2B - 255) \end{cases}

4. 其他特效類

模式名 公式 說明
實色疊加(Hard Mix) C={255(A+B255)0(A+B<255)C = \begin{cases}255 & (A + B \ge 255)\\0 & (A + B < 255)\end{cases} 會使結果只有純色 (非 0 即 255),製造極端色塊效果
差值(Difference) (C = A - B
排除(Exclusion) C=A+BA×B128C = A + B - \dfrac{A \times B}{128} 與差值類似,但結果較柔和
相加(Add) C=A+BC = A + B(若超過 255 則視為疊色 / 補陰) 將像素值相加後再裁切,若值過大即「溢色」。有時用於製作發光效果
減去(Subtract) C=ABC = A - B(若小於 0 則視為 0) 將像素值相減後再裁切,若小於 0 即「補陰」。

5. 小結

  1. 比較類 (變暗 / 變亮) 只做簡單的比較取最小或最大值。
  2. 乘法類 (正片疊底 / 濾色 / 顏色加深 / 顏色減淡 / 線性加深 / 線性減淡) 大多基於「乘法 + 反相」等簡單算式,控制明暗。
  3. 光系混合 (疊加 / 強光 / 柔光 / 亮光 / 點光 / 線性光 / Vivid Light / Linear Light / Pin Light...) 則常用分段函式,依暗部或亮部使用不同算法。
  4. 特效類 (差值 / 排除 / 實色疊加 / 相加 / 減去 ...) 產生反相、門檻化或其他獨特效果。

以上即為根據圖片上列出的混合模式與對應公式所做的整理與歸納。若有個別公式與您實務使用或軟體顯示不符,建議再對照實際的程式碼或官方文件,以取得最準確的數值與算法。希望對您有所幫助。

2024年10月8日 星期二

C# Struct 的自動哈希與相等比較:簡化開發的優勢

### 結論簡短版 `struct` 的一個重要優勢是,在大多數情況下,不需要手動覆寫 `GetHashCode()` 和 `Equals()`。C# 會自動基於 `struct` 的成員生成這些方法,讓開發更簡單並減少錯誤風險。這在需要高效查找和相等比較的情況下非常實用。 ### 範例說明 假設我們有一個 `Point` 結構:


struct Point
{
    public int X { get; }
    public int Y { get; }

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}


在這裡,我們不需要覆寫 `GetHashCode()` 和 `Equals()`,就可以直接將 `Point` 用作 `Dictionary` 的鍵:


var pointsDictionary = new Dictionary();
pointsDictionary[new Point(1, 2)] = "First Point";

// C# 自動處理哈希和相等比較
Console.WriteLine(pointsDictionary[new Point(1, 2)]); // 輸出:First Point


這展示了 `struct` 自動處理哈希和相等比較的方便性,讓我們不必手動覆寫這些方法,仍然可以高效使用字典查找等功能。

2023年10月1日 星期日

PS 混色公式



  1. 變暗:
    C=min(A,B)C = \min(A, B)
    註解:這個公式取A和B兩者之間較暗的顏色,用來使圖像變暗。

  2. 變亮:
    C=max(A,B)C = \max(A, B)
    註解:這個公式取A和B兩者之間較亮的顏色,用來使圖像變亮。

  3. 正片叠底:
    C=A×B255C = \frac{A \times B}{255}
    註解:這是模擬多重曝光的效果,使圖像變得更暗。結果會比變暗更強烈。

  4. 濾色:
    C=255(255A)×(255B)255C = 255 - \frac{(255 - A) \times (255 - B)}{255}
    註解:此公式和正片叠底相反,模擬膠片的濾色效果,用來變亮圖像。

  5. 顏色加深:
    C=A(255A)×(255B)BC = A - \frac{(255 - A) \times (255 - B)}{B}
    註解:這個公式增強圖像的顏色深度,增加對比度。

  6. 顏色減淡:
    C=A+A×B255BC = A + \frac{A \times B}{255 - B}
    註解:這個公式減少顏色的深度,使圖像變得更亮。

  7. 線性加深:
    C=A+B255C = A + B - 255
    註解:將兩個顏色相加,然後減去255,達到加深圖像的效果。

  8. 線性減淡:
    C=A+BC = A + B
    註解:將兩個顏色相加,達到減淡圖像的效果,使畫面變亮。

  9. 強光:
    當 B128,C=A×B128\text{當 } B \leq 128 \text{時}, C = \frac{A \times B}{128}
    當 B>128,C=255(255A)×(255(B128))128\text{當 } B > 128 \text{時}, C = 255 - \frac{(255 - A) \times (255 - (B - 128))}{128}
    註解:這個模式結合了正片叠底和濾色的效果,對比度會變得非常強烈。

  10. 疊加:
    C=A×B128+A255×(2552B)C = \frac{A \times B}{128} + \frac{A}{255} \times (255 - 2B)
    註解:疊加結合了正片叠底和濾色的效果,強化亮區和暗區的對比,適合增強細節。

  11. 柔光:
    當 B128,C=A×B128\text{當 } B \leq 128 \text{時}, C = \frac{A \times B}{128}
    當 B>128,C=A+(A255)×(2552B)128\text{當 } B > 128 \text{時}, C = A + (A - 255) \times \frac{(255 - 2B)}{128}
    註解:柔光模式會根據基色和混合色的亮度不同,適當增強對比,但效果比強光溫和。

  12. 亮光:
    C=min(A,2B255)C = \min(A, 2B - 255)
    註解:這個模式會根據B的值來調整亮度,並且在亮區和暗區有顯著的區別。

  13. 線性光:
    C=A+2B255C = A + 2B - 255
    註解:這是一種強烈的對比模式,增加混合色的亮度,使暗區更暗、亮區更亮。

  14. 實色增值:
    當 A+B255,C=255\text{當 } A + B \geq 255 \text{時}, C = 255
    否則 C=0\text{否則 } C = 0
    註解:此模式類似於正片叠底,但結果只有純黑和純白,無中間過渡。

  15. 排除:
    C=A+BA×B128C = A + B - \frac{A \times B}{128}
    註解:此模式產生類似差值的效果,但更柔和一些,適合創建一些特殊效果。

  16. 差值:
    C=ABC = |A - B|
    註解:此模式將基色和混合色的差異強烈地顯示出來,適合對比圖像中的變化。

  17. 相加:
    C=A+BC = A + B
    註解:這是一個簡單的加法混合模式,兩種顏色的亮度相加,可能會導致圖像變得非常亮。

  18. 相減:
    C=ABC = A - B
    註解:此模式將兩個顏色相減,適合創造圖像的反差效果。

  19. 點光:
    當 B128,C=A×B128\text{當 } B \leq 128 \text{時}, C = \frac{A \times B}{128}
    當 B>128,C=min(A,2B255)\text{當 } B > 128 \text{時}, C = \min(A, 2B - 255)
    註解:這個模式會根據B的亮度不同來決定是變亮還是變暗,類似於點光源的效果。


來源:

 https://blog.csdn.net/pizi0475/article/details/8241774?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-8241774-blog-78193734.235%5Ev38%5Epc_relevant_anti_vip&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-8241774-blog-78193734.235%5Ev38%5Epc_relevant_anti_vip&utm_relevant_index=2

文字描述由 ChatGPT 生成 如有錯誤請指證 請當參考就好

2023年9月14日 星期四

C# int[] to byte[] , byte[] to int[]



public class ByteAyParser
{
    public static byte[] IntAy2ByteAy(int[] intAy)
    {
        int byteCount = intAy.Length * 4;
        byte[] byteAy = new byte[byteCount];

        for (int i = 0; i < intAy.Length; i++)
        {
            int val = intAy[i];
            byteAy[i * 4 + 3] = (byte)((val >> 24) & 0xFF);
            byteAy[i * 4 + 2] = (byte)((val >> 16) & 0xFF);
            byteAy[i * 4 + 1] = (byte)((val >> 8) & 0xFF);
            byteAy[i * 4 + 0] = (byte)(val & 0xFF);
        }

        return byteAy;
    }
    public static int[] ByteAy2IntAy(byte[] byteAy)
    {
        if (byteAy.Length % 4 != 0)
        {
            Debug.LogErrorFormat("ByteAy2IntAy byteAy.Length {0} not a multiple of 4", byteAy.Length);
            return null;
        }

        int intCount = byteAy.Length >> 2;// 除4
        int[] intArray = new int[intCount];

        for (int i = 0; i < intCount; i++)
        {
            int val = 0;
            val |= byteAy[i * 4 + 3] << 24;
            val |= byteAy[i * 4 + 2] << 16;
            val |= byteAy[i * 4 + 1] << 8;
            val |= byteAy[i * 4];
            intArray[i] = val;
        }

        return intArray;
    }
}

public class ByteAyParserTester
{
    [Test]
    public void IsMatch()
    {
        int[] intAy = new int[] { -1, 0, 1, };
        byte[] bAy = ByteAyParser.IntAy2ByteAy(intAy);
        int[] intAyBack = ByteAyParser.ByteAy2IntAy(bAy);

        for (int i = 0; i < intAy.Length; i++)
        {
            if (intAy[i] != intAyBack[i])
            {
                Debug.LogErrorFormat("No Match intAy[{0}] {1} , intAyBack[{0}] {2}", i, intAy[i], intAyBack[i]);
                Assert.Fail();
            }
        }
    }

    [Test]
    public void IsMatchLimit()
    {
        int[] intAy = new int[] { int.MinValue, int.MinValue };
        byte[] bAy = ByteAyParser.IntAy2ByteAy(intAy);
        int[] intAyBack = ByteAyParser.ByteAy2IntAy(bAy);

        for (int i = 0; i < intAy.Length; i++)
        {
            if (intAy[i] != intAyBack[i])
            {
                Debug.LogErrorFormat("No Match intAy[{0}] {1} , intAyBack[{0}] {2}", i, intAy[i], intAyBack[i]);
                Assert.Fail();
            }
        }
    }
}



2023年8月31日 星期四

C# Return Mutiple Value , C# 回傳多個值

結論:


使用(int,int)最佳 , 沒GC可讀性高 可定義變數名稱


ValueTuple<int, int> 等價於 (int,int) 不可定義變數名稱
out int a , out int b 舊版C#適用
Tuple<int, int> Reference Type 不建議使用 會GC
範例:



// ValueTuple<int, int> 屬於 Value Type , 不會產生 GC
public ValueTuple<int, int> GET3()
{
    return new ValueTuple<int, int>(1, 2);
}

// ValueTuple<int, int> 等價於 (int, int) 屬於語法糖 可以互轉
public (int a, int b) GET1()
{
    return (1, 2);
}

// ValueTuple<int, int> 等價於 (int, int) 屬於語法糖 可以互轉
public ValueTuple<int, int> GET4()
{
    //簡易寫法
    return (1, 2);
}

public (int a, int b) GET2()
{
    //可自定義變數名稱 可讀性比較好
    (int a, int b) val;
    val.a = 1;
    val.b = 2;
    return val;
}

// Tuple<int,int> 屬於 Reference Type , 會產生 GC
public Tuple<int, int> GET5()
{
    return new Tuple<int, int>(1, 2);
}

// 用 out 參數直接改值
public void GET(out int a, out int b)
{
    a = 1;
    b = 2;
}