用Python做股市數據分析(二)

来源:https://www.cnblogs.com/jingsupo/archive/2018/03/20/Stock-Market-Data-Analysis-with-Python-Part2.html
-Advertisement-
Play Games

本文由 伯樂線上 - 小米雲豆粥 翻譯。未經許可,禁止轉載!英文出處:Curtis Miller。歡迎加入翻譯組。 這篇博文是用Python分析股市數據系列兩部中的第二部,內容基於我在猶他大學 數學3900 (數據科學)的課程 (閱讀第一部分)。在這兩篇博文中,我會討論一些基礎知識,包括比如如何用p ...


本文由 伯樂線上 - 小米雲豆粥 翻譯。未經許可,禁止轉載!
英文出處:Curtis Miller。歡迎加入翻譯組

這篇博文是用Python分析股市數據系列兩部中的第二部,內容基於我在猶他大學 數學3900 (數據科學)的課程 (閱讀第一部分)。在這兩篇博文中,我會討論一些基礎知識,包括比如如何用pandas從雅虎財經獲得數據, 可視化股市數據,平均數指標的定義,設計移動平均交匯點分析移動平均線的方法,回溯測試和 基準分析法。這篇文章會討論如何設計用移動平均交匯點分析移動平均線的系統,如何做回溯測試和基準分析,最後留有一些練習題以饗讀者。

註意:本文僅代表作者本人的觀點。文中的內容不應該被當做經濟建議。我不對文中代碼負責,取用者自己負責

交易策略

在特定的預期條件達成時一個開放頭寸會被關閉。多頭頭寸表示交易中需要金融商品價格上升才能產生盈利,空頭頭寸表示交易中需要金融商品價格下降才能產生盈利。在股票交易中,多頭頭寸是牛市,空頭頭寸是熊市,反之則不成立。(股票期權交易中這個非常典型)

例如你在預計股價上漲的情況下購入股票,並計劃在股票價格上漲高於購入價時拋出,這就是多頭頭寸。就是說你持有一定的金融產品,如果它們價格上漲,你將會獲利,並且沒有上限;如果它們價格下降,你會虧損。由於股票價格不會為負,虧損是有限度的。相反的,如果你預計股價會下跌,就從交易公司借貸股票然後賣出,同時期待未來股票價格下降後再低價買入還貸來賺取差額,這就是空頭股票。如果股價下跌你會獲利。空頭頭寸的獲利額度受股價所限(最佳情況就是股票變得一文不值,你不用花錢就能將它們買回來),而損失卻沒有下限,因為你有可能需要花很多錢才能買回股票。所以交換所只會在確定投資者有很好的經濟基礎的情況下才會讓他們空頭借貸股票。

所有股民都應該決定他在每一股上可以冒多大的風險。比如有人決定無論什麼情況他都不會在某一次交易中投入總額的10%去冒險。同時在交易中,股民要有一個撤出策略,這是讓股民退出頭寸的各種條件。股民也可以設置一個目標,這是導致股民退出頭寸的最小盈利額。同樣的,股民也需要有一個他能承受的最大損失額度。當預計損失大於可承受額度時,股民應該退出頭寸以避免更大損失(這可以通過設置停止損失委托來避免未來的損失)。

我們要設計一個交易策略,它包含用於快速交易的交易激發信號、決定交易額度的規則和完整的退出策略。我們的目標是設計並評估該交易策略。

假設每次交易金額占總額的比例是固定的(10%)。同時設定在每一次交易中,如果損失超過了20%的交易值,我們就退出頭寸。現在我們要決定什麼時候進入頭寸,什麼時候退出以保證盈利。

這裡我要演示移動平均交匯點分析移動平均線的方法。我會使用兩條移動平均線,一條快速的,另一條是慢速的。我們的策略是:

  • 當快速移動平均線和慢速移動線交匯時開始交易
  • 當快速移動平均線和慢速移動線再次交匯時停止交易

做多是指在快速平均線上升到慢速平均線之上時開始交易,當快速平均線下降到慢速平均線之下時停止交易。賣空正好相反,它是指在快速平均線下降到慢速平均線之下時開始交易,快速平均線上升到慢速平均線之上時停止交易。

現在我們有一整套策略了。在使用它之前我們需要先做一下測試。回溯測試是一個常用的測試方法,它使用歷史數據來看策略是否會盈利。例如這張蘋果公司的股票價值圖,如果20天的移動平均是快速線,50天的移動平均是慢速線,那麼我們這個策略不是很掙錢,至少在你一直做多頭頭寸的時候。

下麵讓我們來自動化回溯測試的過程。首先我們要識別什麼時候20天平均線在50天之下,以及之上。

apple['20d-50d'] =apple['20d'] -apple['50d']
apple.tail()
OpenHighLowCloseVolumeAdj Close20d50d200d20d-50d
Date
2016-08-26 107.410004 107.949997 106.309998 106.940002 27766300 106.940002 107.87 101.51 102.73 6.36
2016-08-29 106.620003 107.440002 106.290001 106.820000 24970300 106.820000 107.91 101.74 102.68 6.17
2016-08-30 105.800003 106.500000 105.500000 106.000000 24863900 106.000000 107.98 101.96 102.63 6.02
2016-08-31 105.660004 106.570000 105.639999 106.099998 29662400 106.099998 108.00 102.16 102.60 5.84
2016-09-01 106.139999 106.800003 105.620003 106.730003 26643600 106.730003 108.04 102.39 102.56 5.65

我們將差異的符號稱為狀態轉換。快速移動平均線在慢速移動平均線之上代表牛市狀態;相反則為熊市。以下的代碼用於識別狀態轉換。

# np.where() is a vectorized if-else function, where a condition is checked for each component of a vector, and the first argument passed is used when the condition holds, and the other passed if it does not
apple["Regime"] = np.where(apple['20d-50d'] > 0, 1, 0)
# We have 1's for bullish regimes and 0's for everything else. Below I replace bearish regimes's values with -1, and to maintain the rest of the vector, the second argument is apple["Regime"]
apple["Regime"] = np.where(apple['20d-50d'] < 0, -1, apple["Regime"])
apple.loc['2016-01-01':'2016-08-07',"Regime"].plot(ylim = (-2,2)).axhline(y = 0, color = "black", lw = 2)

apple["Regime"].plot(ylim =(-2,2)).axhline(y =0, color ="black", lw =2)

apple["Regime"].value_counts()
 1    966
-1    663
 0     50
Name: Regime, dtype: int64

從上面的曲線可以看到有966天蘋果公司的股票是牛市,663天是熊市,有54天沒有傾向性。(原文中牛市和熊市說反了,譯文中更正;原文數字跟代碼結果對不上,譯文按照代碼結果更正)

交易信號出現在狀態轉換之時。牛市出現時,買入信號被激活;牛市完結時,賣出信號被激活。同樣的,熊市出現時賣出信號被激活,熊市結束時,買入信號被激活。(只有在你空頭股票,或者使用一些其他的方法例如用股票期權賭市場的時候這種情況才對你有利)

# To ensure that all trades close out, I temporarily change the regime of the last row to 0
regime_orig = apple.ix[-1, "Regime"]
apple.ix[-1, "Regime"] = 0
apple["Signal"] = np.sign(apple["Regime"] - apple["Regime"].shift(1))
# Restore original regime data
apple.ix[-1, "Regime"] = regime_orig
apple.tail()
OpenHighLowCloseVolumeAdj Close20d50d200d20d-50dRegimeSignal
Date
2016-08-26 107.410004 107.949997 106.309998 106.940002 27766300 106.940002 107.87 101.51 102.73 6.36 1.0 0.0
2016-08-29 106.620003 107.440002 106.290001 106.820000 24970300 106.820000 107.91 101.74 102.68 6.17 1.0 0.0
2016-08-30 105.800003 106.500000 105.500000 106.000000 24863900 106.000000 107.98 101.96 102.63 6.02 1.0 0.0
2016-08-31 105.660004 106.570000 105.639999 106.099998 29662400 106.099998 108.00 102.16 102.60 5.84 1.0 0.0
2016-09-01 106.139999 106.800003 105.620003 106.730003 26643600 106.730003 108.04 102.39 102.56 5.65 1.0 -1.0
 
apple["Signal"].plot(ylim =(-2, 2))

apple["Signal"].value_counts()
 0.0    1637
-1.0      21
 1.0      20
Name: Signal, dtype: int64

我們會買入蘋果公司的股票20次,拋出21次 (原文數字跟代碼結果不符,譯文根據代碼結果更正)。如果我們只選了蘋果公司的股票,六年內只有21次交易發生。如果每次多頭轉空頭的時候我們都採取行動,我們將會參與21次交易。(請記住交易次數不是越多越好,畢竟交易不是免費的)

你也許註意到了這個系統不是很穩定。快速平均線在慢速平均線之上就激發交易,即使這個狀態只是短短一瞬,這樣會導致交易馬上終止(這樣並不好因為現實中每次交易都要付費,這個費用會很快消耗掉收益)。同時所有的牛市瞬間轉為熊市,如果你允許同時押熊市和牛市,那就會出現每次交易結束就自動激發另一場押相反方向交易的詭異情況。更好的系統會要求有更多的證據來證明市場的發展方向,但是這裡我們不去追究那個細節。

下麵我們來看看每次買入賣出時候的股票價格。

apple.loc[apple["Signal"] ==1, "Close"]
Date
2010-03-16    224.449997
2010-06-18    274.070011
2010-09-20    283.230007
2011-05-12    346.569988
2011-07-14    357.770004
2011-12-28    402.640003
2012-06-25    570.770020
2013-05-17    433.260010
2013-07-31    452.529984
2013-10-16    501.110001
2014-03-26    539.779991
2014-04-25    571.939980
2014-08-18     99.160004
2014-10-28    106.739998
2015-02-05    119.940002
2015-04-28    130.559998
2015-10-27    114.550003
2016-03-11    102.260002
2016-07-01     95.889999
2016-07-25     97.339996
Name: Close, dtype: float64
apple.loc[apple["Signal"] ==-1, "Close"]
Date
2010-06-11    253.509995
2010-07-22    259.020000
2011-03-30    348.630009
2011-03-31    348.510006
2011-05-27    337.409992
2011-11-17    377.410000
2012-05-09    569.180023
2012-10-17    644.610001
2013-06-26    398.069992
2013-10-03    483.409996
2014-01-28    506.499977
2014-04-22    531.700020
2014-06-11     93.860001
2014-10-17     97.669998
2015-01-05    106.250000
2015-04-16    126.169998
2015-06-25    127.500000
2015-12-18    106.029999
2016-05-05     93.239998
2016-07-08     96.680000
2016-09-01    106.730003
Name: Close, dtype: float64
# Create a DataFrame with trades, including the price at the trade and the regime under which the trade is made.
apple_signals = pd.concat([
        pd.DataFrame({"Price": apple.loc[apple["Signal"] == 1, "Close"],
                     "Regime": apple.loc[apple["Signal"] == 1, "Regime"],
                     "Signal": "Buy"}),
        pd.DataFrame({"Price": apple.loc[apple["Signal"] == -1, "Close"],
                     "Regime": apple.loc[apple["Signal"] == -1, "Regime"],
                     "Signal": "Sell"}),
    ])
apple_signals.sort_index(inplace = True)
apple_signals

 

Price

Regime

Signal

 

Date

 

 

 

2010-03-16

224.449997

1.0

Buy

2010-06-11

253.509995

-1.0

Sell

2010-06-18

274.070011

1.0

Buy

2010-07-22

259.020000

-1.0

Sell

2010-09-20

283.230007

1.0

Buy

2011-03-30

348.630009

0.0

Sell

2011-03-31

348.510006

-1.0

Sell

2011-05-12

346.569988

1.0

Buy

2011-05-27

337.409992

-1.0

Sell

2011-07-14

357.770004

1.0

Buy

2011-11-17

377.410000

-1.0

Sell

2011-12-28

402.640003

1.0

Buy

2012-05-09

569.180023

-1.0

Sell

2012-06-25

570.770020

1.0

Buy

2012-10-17

644.610001

-1.0

Sell

2013-05-17

433.260010

1.0

Buy

2013-06-26

398.069992

-1.0

Sell

2013-07-31

452.529984

1.0

Buy

2013-10-03

483.409996

-1.0

Sell

2013-10-16

501.110001

1.0

Buy

2014-01-28

506.499977

-1.0

Sell

2014-03-26

539.779991

1.0

Buy

2014-04-22

531.700020

-1.0

Sell

2014-04-25

571.939980

1.0

Buy

2014-06-11

93.860001

-1.0

Sell

2014-08-18

99.160004

1.0

Buy

2014-10-17

97.669998

-1.0

Sell

2014-10-28

106.739998

1.0

Buy

2015-01-05

106.250000

-1.0

Sell

2015-02-05

119.940002

1.0

Buy

2015-04-16

126.169998

-1.0

Sell

2015-04-28

130.559998

1.0

Buy

2015-06-25

127.500000

-1.0

Sell

2015-10-27

114.550003

1.0

Buy

2015-12-18

106.029999

-1.0

Sell

2016-03-11

102.260002

1.0

Buy

2016-05-05

93.239998

-1.0

Sell

2016-07-01

95.889999

1.0

Buy

2016-07-08

96.680000

-1.0

Sell

2016-07-25

97.339996

1.0

Buy

2016-09-01

106.730003

1.0

Sell

# Let's see the profitability of long trades
apple_long_profits = pd.DataFrame({
        "Price": apple_signals.loc[(apple_signals["Signal"] == "Buy") &
                                  apple_signals["Regime"] == 1, "Price"],
        "Profit": pd.Series(apple_signals["Price"] - apple_signals["Price"].shift(1)).loc[
            apple_signals.loc[(apple_signals["Signal"].shift(1) == "Buy") & (apple_signals["Regime"].shift(1) == 1)].index
        ].tolist(),
        "End Date": apple_signals["Price"].loc[
            apple_signals.loc[(apple_signals["Signal"].shift(1) == "Buy") & (apple_signals["Regime"].shift(1) == 1)].index
        ].index
    })
apple_long_profits
End DatePriceProfit
Date
2010-03-16 2010-06-11 224.449997 29.059998
2010-06-18 2010-07-22 274.070011 -15.050011
2010-09-20 2011-03-30 283.230007 65.400002
2011-05-12 2011-05-27 346.569988 -9.159996
2011-07-14 2011-11-17 357.770004 19.639996
2011-12-28 2012-05-09 402.640003 166.540020
2012-06-25 2012-10-17 570.770020 73.839981
2013-05-17 2013-06-26 433.260010 -35.190018
2013-07-31 2013-10-03 452.529984 30.880012
2013-10-16 2014-01-28 501.110001 5.389976
2014-03-26 2014-04-22 539.779991 -8.079971
2014-04-25 2014-06-11 571.939980 -478.079979
2014-08-18 2014-10-17 99.160004 -1.490006
2014-10-28 2015-01-05 106.739998 -0.489998
2015-02-05 2015-04-16 119.940002 6.229996
2015-04-28 2015-06-25 130.559998 -3.059998
2015-10-27 2015-12-18 114.550003 -8.520004
2016-03-11 2016-05-05 102.260002 -9.020004
2016-07-01 2016-07-08 95.889999 0.790001
2016-07-25 2016-09-01 97.339996 9.390007

從上表可以看出2013年5月17日那天蘋果公司股票價格大跌,我們的系統會表現很差。但是那個價格下降不是因為蘋果遇到了什麼大危機,而僅僅是一次分股。由於分紅不如分股那麼顯著,這也許會影響系統行為。

# Let's see the result over the whole period for which we have Apple data
pandas_candlestick_ohlc(apple, stick = 45, otherseries = ["20d", "50d", "200d"])

我們不希望我們的交易系統的表現受到分紅和分股的影響。一個解決方案是利用歷史的分紅分股數據來設計交易系統,這些數據可以真實地反映股市的行為從而幫助我們找到最佳解決方案,但是這個方法要更複雜一些。另一個方案就是根據分紅和分股來調整股票的價格。

雅虎財經只提供調整之後的股票閉市價格,不過這些對於我們調整開市,高價和低價已經足夠了。調整閉市股價是這樣實現的:

讓我們回到開始,先調整股票價格,然後再來評價我們的交易系統。

def ohlc_adj(dat):
    """
    :param dat: pandas DataFrame with stock data, including "Open", "High", "Low", "Close", and "Adj Close", with "Adj Close" containing adjusted closing prices
 
    :return: pandas DataFrame with adjusted stock data
 
    This function adjusts stock data for splits, dividends, etc., returning a data frame with
    "Open", "High", "Low" and "Close" columns. The input DataFrame is similar to that returned
    by pandas Yahoo! Finance API.
    """
    return pd.DataFrame({"Open": dat["Open"] * dat["Adj Close"] / dat["Close"],
                       "High": dat["High"] * dat["Adj Close"] / dat["Close"],
                       "Low": dat["Low"] * dat["Adj Close"] / dat["Close"],
                       "Close": dat["Adj Close"]})
 
apple_adj = ohlc_adj(apple)
 
# This next code repeats all the earlier analysis we did on the adjusted data
 
apple_adj["20d"] = np.round(apple_adj["Close"].rolling(window = 20, center = False).mean(), 2)
apple_adj["50d"] = np.round(apple_adj["Close"].rolling(window = 50, center = False).mean(), 2)
apple_adj["200d"] = np.round(apple_adj["Close"].rolling(window = 200, center = False).mean(), 2)
 
apple_adj['20d-50d'] = apple_adj['20d'] - apple_adj['50d']
# np.where() is a vectorized if-else function, where a condition is checked for each component of a vector, and the first argument passed is used when the condition holds, and the other passed if it does not
apple_adj["Regime"] = np.where(apple_adj['20d-50d'] > 0, 1, 0)
# We have 1's for bullish regimes and 0's for everything else. Below I replace bearish regimes's values with -1, and to maintain the rest of the vector, the second argument is apple["Regime"]
apple_adj["Regime"] = np.where(apple_adj['20d-50d'] < 0, -1, apple_adj["Regime"])
# To ensure that all trades close out, I temporarily change the regime of the last row to 0
regime_orig = apple_adj.ix[-1, "Regime"]
apple_adj.ix[-1, "Regime"] = 0
apple_adj["Signal"] = np.sign(apple_adj["Regime"] - apple_adj["Regime"].shift(1))
# Restore original regime data
apple_adj.ix[-1, "Regime"] = regime_orig
 
# Create a DataFrame with trades, including the price at the trade and the regime under which the trade is made.
apple_adj_signals = pd.concat([
        pd.DataFrame({"Price": apple_adj.loc[apple_adj["Signal"] == 1, "Close"],
                     "Regime": apple_adj.loc[apple_adj["Signal"] == 1, "Regime"],
                     "Signal": "Buy"}),
        pd.DataFrame({"Price": apple_adj.loc[apple_adj["Signal"] == -1, "Close"],
                     "Regime": apple_adj.loc[apple_adj["Signal"] == -1, "Regime"],
                     "Signal": "Sell"}),
    ])
apple_adj_signals.sort_index(inplace = True)
apple_adj_long_profits = pd.DataFrame({
        "Price": apple_adj_signals.loc[(apple_adj_signals["Signal"] == "Buy") &
                                  apple_adj_signals["Regime"] == 1, "Price"],
        "Profit": pd.Series(apple_adj_signals["Price"] - apple_adj_signals["Price"].shift(1)).loc[
            apple_adj_signals.loc[(apple_adj_signals["Signal"].shift(1) == "Buy") & (apple_adj_signals["Regime"].shift(1) == 1)].index
        ].tolist(),
        "End Date": apple_adj_signals["Price"].loc[
            apple_adj_signals.loc[(apple_adj_signals["Signal"].shift(1) == "Buy") & (apple_adj_signals["Regime"].shift(1) == 1)].index
        ].index
    })
 
pandas_candlestick_ohlc(apple_adj, stick = 45, otherseries = ["20d", "50d", "200d"])


apple_adj_long_profits
End DatePriceProfit
Date
2010-03-16 2010-06-10 29.355667 3.408371
2010-06-18 2010-07-22 35.845436 -1.968381
2010-09-20 2011-03-30 37.043466 8.553623
2011-05-12 2011-05-27 45.327660 -1.198030
2011-07-14 2011-11-17 46.792503 2.568702
2011-12-28 2012-05-09 52.661020 21.781659
2012-06-25 2012-10-17 74.650634 10.019459
2013-05-17 2013-06-26 57.882798 -4.701326
2013-07-31 2013-10-04 60.457234 4.500835
2013-10-16 2014-01-28 67.389473 1.122523
2014-03-11 2014-03-17 72.948554 -1.272298
2014-03-24 2014-04-22 73.370393 -1.019203
2014-04-25 2014-10-17 77.826851 16.191371
2014-10-28 2015-01-05 102.749105 -0.028185
2015-02-05 2015-04-16 116.413846 6.046838
2015-04-28 2015-06-26 126.721620 -3.184117
2015-10-27 2015-12-18 112.152083 -7.897288
2016-03-10 2016-05-05 100.015950 -7.278331
2016-06-23 2016-06-27 95.582210 -4.038123
2016-06-30 2016-07-11 95.084904 1.372569
2016-07-25 2016-09-01 96.815526 9.914477

可以看到根據分紅和分股調整之後的價格圖變得很不一樣了。之後的分析我們都會用到這個調整之後的數據。

假設我們在股市有一百萬,讓我們來看看根據下麵的條件,我們的系統會如何反應:

  • 每次用總額的10%來進行交易
  • 退出頭寸如果虧損達到了交易額的20%

模擬的時候要記住:

  • 每次交易有100支股票
  • 我們的避損規則是當股票價格下降到一定數值時就拋出。我們需要檢查這段時間內的低價是否低到可以出發避損規則。現實中除非我們買入看空期權,我們無法保證我們能以設定低值價格賣出股票。這裡為了簡潔我們將設定值作為賣出值。
  • 每次交易都會付給中介一定的佣金。這裡我們沒有考慮這個。

下麵的代碼演示瞭如何實現回溯測試:

# We need to get the low of the price during each trade.
tradeperiods =pd.DataFrame({"Start": apple_adj_long_profits.index,
                            "End": apple_adj_long_profits["End Date"]})
apple_adj_long_profits["Low"] =tradeperiods.apply(lambdax: min(apple_adj.loc[x["Start"]:x["End"], "Low"]), axis =1)
apple_adj_long_profits

 

End Date

Price

Profit

Low

 

Date

 

 

 

 

2010-03-16

2010-06-10

29.355667

3.408371

26.059775

2010-06-18

2010-07-22

35.845436

-1.968381

31.337127

2010-09-20

2011-03-30

37.043466

8.553623

35.967068

2011-05-12

2011-05-27

45.327660

-1.198030

43.084626

2011-07-14

2011-11-17

46.792503

2.568702

46.171251

2011-12-28

2012-05-09

52.661020

21.781659

52.382438

2012-06-25

2012-10-17

74.650634

10.019459

73.975759

2013-05-17

2013-06-26

57.882798

-4.701326

52.859502

2013-07-31

2013-10-04

60.457234

4.500835

60.043080

2013-10-16

2014-01-28

67.389473

1.122523

67.136651

2014-03-11

2014-03-17

72.948554

-1.272298

71.167335

2014-03-24

2014-04-22

73.370393

-1.019203

69.579335

2014-04-25

2014-10-17

77.826851

16.191371

76.740971

2014-10-28

2015-01-05

102.749105

-0.028185

101.411076

2015-02-05

2015-04-16

116.413846

6.046838

114.948237

2015-04-28

2015-06-26

126.721620

-3.184117

119.733299

2015-10-27

2015-12-18

112.152083

-7.897288

104.038477

2016-03-10

2016-05-05

100.015950

-7.278331

91.345994

2016-06-23

2016-06-27

95.582210

-4.038123

91.006996

2016-06-30

2016-07-11

95.084904

1.372569

93.791913

2016-07-25

2016-09-01

96.815526

9.914477

95.900485

# Now we have all the information needed to simulate this strategy in apple_adj_long_profits
cash =1000000
apple_backtest =pd.DataFrame({"Start Port. Value": [],
                         "	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • React項目的單元測試 React的組件結構和JSX語法,對 "上一章" 的內容來講進行測試顯得很勉強。 React官方已經提供了一個測試工具庫: "react dom/test utils" 只是用起來不夠方便,於是有了一些第三方的封裝庫,比如Airbnb公司的 "Enzyme" 測試項目的配置 ...
  • 最近徘徊在找工作和繼續留任的糾結之中,在朋友的慫恿下去參加了一次面試,最後一道題目是: 寫一個函數,輸入一個字元串的運算式,返回計算之後的結果。例如這樣的: '1 + (5 2) 3',計算出結果為10 最開始看到這個題目的時候,我腦中的第一反應就是 ,真的太直接了。但是我就不明白為什麼這竟然是最後 ...
  • 資料來源:有群里的朋友給我的一些資料,以及自己百度和論壇、社區找來的一些資料,權當做一個總結式的簡介。。。 目錄如下: 一、微服務架構介紹 二、出現和發展 三、傳統開發模式和微服務的區別 四、微服務的具體特征 五、SOA和微服務的區別 六、如何具體實踐微服務 七、常見的微服務設計模式和應用 八、微服 ...
  • 在.Net框架中很多對象的方法中都會有Invoke方法,這種方法的設計實際是用了設計模式的命令模式, 模式圖如下 其核心思路是將Client 向Receiver發送的命令行為進行抽象(ICommand),實例化(ConcreteCommand),以便對這些行為能夠控制(記錄,取消,恢復); 每個Co ...
  • 第一章 設計模式入門 1.好詞好句: 好的設計是可以應付改變。 2.驅動改變的因素:(a)客戶需求不清晰,後期會一直變 (b)遇到坑爹的產品,自己不會全扔給程式員 (c)在開發過程中,產生一個新概念,改還是不改? 3.設計原則: (1)找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化 ...
  • 1. jdk中的進位轉換 十進位轉十六進位 十進位轉八進位 十進位轉二進位 十六進位轉十進位 八進位轉十進位 二進位轉十進位 2. java中的數據類型 ...
  • 堆:(對象) 引用類型的變數,其記憶體分配在堆上或者常量池(字元床常量、基本數據類型常量),需要通過new等方式來創建。 對記憶體主要作用是存放運行是創建(new)的對象。 (主要用於存放對象,存取速度慢,可以運行時動態分配記憶體,生存期不需要提前確定) 棧:(基本數據類型變數,對象的引用變數) 棧記憶體的 ...
  • 字元串切片 字元串切片屬於字元串運算符的一種 切片操作就是從字元串中截取我們想要的子字元串 語法格式:str[ start, end, step] start 開始位置 end 結束位置(不包含) step 步長(預設為 1 ) 常用的操作 [ : ] 提取整個字元串 [ start: ] 提取 s ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...