如何第一次量化交易就賠錢

更新於 發佈於 閱讀時間約 23 分鐘
投資理財內容聲明

如何第一次量化交易投資就賠錢

身為會寫一點程式碼的工程師,量化交易投資無疑是最具吸引力的投資方式。試想只要寫個小程式定期去追蹤股市大盤交易指數,然後自動下單買入賣出,就會賺進源源不絕的財富,光用想的口水都快流下來了。

坐而言不如起而行。這邊有幾個小問題需要克服:

  1. 即時報價
  2. 下單買賣
  3. 交易策略

市面上有許多現成軟體都可以做到上述功能,例如TradingView、MultiCharts或是XQ,但是都需要繳交不少的年費。還好有些券商願意提供報價與下單的API,例如群益與永豐,只要開戶成功,就可以自行DIY寫程式免費去使用這些API達成前兩項功能。筆者自己是採用群益API,主要是因為API文件解說詳細,而且可以在網路上找到不少範例,開發相對較為快速。

接下來重點就是交易策略了。依據筆者個人初淺的調查研究,交易策略可以分成順勢交易與逆勢交易。順勢交易主要判斷方式就是找出一個震盪區間,一旦往上或是往下突破這個震盪區間,就立刻開始買多或是賣空。逆勢交易就是傳說中的摸頭猜底,網路上許多神人可以透過各種波浪理論準確預言價格高低點,可惜大多採用形態學劃線的方式,筆者功力淺薄,還想不出方式將形態學改寫成為程式邏輯。所以本文會採用順勢交易策略,透過一些指標計算當作範例。交易週期也是交易策略中重要的一環,既然有了電腦無時無刻幫忙監控,當然可以選擇較短的交易週期,筆者瀏覽許多網路文章之後,就先選定台指期5分K當作目標。目前券商提供的API都有C#以及Python版本,因為筆者本身對C語言比較熟悉,所以就選了C#當作實作語言。

程式框架很簡單,分成兩個主要的部份: 1. 讀取券商即時報價tick,並立刻轉換成為1分K或是5分K的資料,以及 2. 每5分鐘讀取一次5分K的資料,帶入指標計算,判斷目前是否為合適的買賣點,如果是的話,執行下單的動作。在開發的過程中,筆者自行摸索許多網路資源,趁著還有些力氣將之記錄下來。

  • 讀取券商即時報價,群益金融網 - 證券API提供註冊個股報價功能,並透過Notify之類的回呼函式取得即時報價。例如筆者想取得的個股報價為台指期,因此註冊的個股代號為「TX00」,若是小台指則為「MTX00」,其中00表示當月報價,如果有指定特別月份報價,則修改00為該月份數字。由於某些時候瞬間的台指期成交筆數非常多,所以儲存資料時建議採用ConcurrentQueue的方式,否則資料很容易就遺失。
  • 指標計算部分,筆者藉由Stock Indicators for .NET函式庫幫忙,以節省自行開發的時間。Skender的指標函式庫涵蓋了許多常見指標,並且持續在github提供更新,對於研究交易指標的原理,不失為良好的研究來源。
  • 即時Tick資料轉OHLC的K棒資料格式,筆者參考[利用 LINQ 實現期指Tick檔彙整為K棒]再稍微改寫符合自己的需求如下,這段 LINQ程式寫得非常高明,筆者感悟一陣子才了解。
        private IEnumerable<OHLCBar> generate_OHLCBar(IEnumerable<Tick> ticks, long barSizeInTicks)
{
TimeSpan natural_time = new TimeSpan(8, 45, 0);

var bars = from tick in ticks
let barIndexForDay = Math.Floor(tick.Timestamp.TimeOfDay.Subtract(natural_time).TotalSeconds / barSizeInTicks)
let barBeginDateTime = tick.Timestamp.Date.Add(natural_time).AddSeconds(barIndexForDay * barSizeInTicks)
let barEndDateTime = tick.Timestamp.Date.Add(natural_time).AddSeconds((barIndexForDay + 1) * barSizeInTicks)
group tick by new { barBeginDateTime, barEndDateTime, tick.Symbol } into tickGroup
orderby tickGroup.Key.barBeginDateTime
let orderedPrices = tickGroup.OrderBy(t => t.Timestamp).Select(t => t.Price)
select new OHLCBar()
{
Symbol = tickGroup.Key.Symbol,
OPEN = orderedPrices.First(),
CLOSE = orderedPrices.Last(),
HIGH = orderedPrices.Max(),
LOW = orderedPrices.Min(),
VOLUME = Convert.ToUInt32(tickGroup.Sum(t => t.Volume)),
BeginTime = tickGroup.Key.barBeginDateTime,
EndTime = tickGroup.Key.barEndDateTime,
Interval = new TimeSpan(0, 0, (int)barSizeInTicks)
};
return bars;
}
  • 台股交易日期則需要至臺灣證券交易所的OpenAPI查詢。筆者拼湊了個簡單的抓取程式如下。但是必須注意的是臺灣證券交易所把春節年假前的交易日期混在停止交易的日期中,所以就算抓下來之後,還要自行修改內容才能直接當作IsHoliday使用。希望有人能反映給臺灣證券交易所,這種資料是給電腦看的,不是給人看的,格式不要亂塞一通。
        private async Task GetHolidayInfo(string path)
{
string req = "https://openapi.twse.com.tw/v1/holidaySchedule/holidaySchedule";
string csv = await GetHttpData(req);
File.WriteAllText(path, csv);
}
private async Task<string> GetHttpData(string weblink)
{
HttpClientHandler handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;

HttpClient client = new HttpClient(handler);

try
{
HttpResponseMessage response = await client.GetAsync(weblink);

response.EnsureSuccessStatusCode();

string responseBody = await response.Content.ReadAsStringAsync();
string csv = jsonToCSV(responseBody, ",");

return csv;
}
catch (HttpRequestException e)
{
Debug.WriteLine("Exception Caught! Message :{0} ", e.Message);
return null;
}
}
private static DataTable jsonStringToTable(string jsonContent)
{
DataTable dt = JsonConvert.DeserializeObject<DataTable>(jsonContent);
return dt;
}
private static string jsonToCSV(string jsonContent, string delimiter)
{
StringWriter csvString = new StringWriter();
var configuration = new CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = delimiter,
MissingFieldFound = null
};
using (var csv = new CsvWriter(csvString, configuration))
{
using (var dt = jsonStringToTable(jsonContent))
{
foreach (DataColumn column in dt.Columns)
{
csv.WriteField(column.ColumnName);
}
csv.NextRecord();

foreach (DataRow row in dt.Rows)
{
for (var i = 0; i < dt.Columns.Count; i++)
{
csv.WriteField(row[i]);
}
csv.NextRecord();
}
}
}
return csvString.ToString();
}
  • 月結算的交易時間與平常日不同,月結算當日比較早收盤,同時還有轉倉的問題,所以筆者也拼湊判斷月結算的函式如下:
        public static bool IsMonthExpDate(this DateTime d)
{
if (GetMonthExpDate(d).Date == d.Date)
{
return true;
}
return false;
}
private static DateTime GetMonthExpDate(DateTime date) // 取得月份到期日(當月第3個星期三)
{
// 本月第一天
DateTime firstDay = new DateTime(date.Year, date.Month, 1, 14, 0, 0);
// 找到第一個星期三
while (firstDay.DayOfWeek != DayOfWeek.Wednesday)
{
firstDay = firstDay.AddDays(1);
}
firstDay = firstDay.AddDays(14);
// 長假順延
while (IsHoliday(firstDay))
{
firstDay = firstDay.AddDays(1);
}
return firstDay;
}
public static string GetFutureYM(DateTime date) // 取得該日應交易的年月份
{
int year = Convert.ToInt32(date.Year.ToString());
int month = date.Month;
DateTime monthExp = GetMonthExpDate(date);
if (date > monthExp)
{
month += 1;
if (month == 13)
{
month = 1;
year = year + 1;
}
}
string FutureYM = year + month.ToString("00");
return FutureYM;
}
  • 資料暫存區,因為Tick資料筆數太多,直接存放在SSD硬碟裡會造成讀寫遲緩以及影響SSD硬碟壽命的問題,所以筆者利用AMD Radeon(TM) RAMDisk在DDR記憶體中開了個Z槽當作頻繁資料存取之用。每天早上5點夜盤結束之後,才備份回一般的硬碟裡。當然這期間要祈禱主機沒當機或是斷電關機。

至於交易策略部分,筆者嘗試過一些天馬行空的交易策略,是還沒找到甚麼聖杯,大部分的交易策略幾乎都是賠錢的。為了本文的完整度,筆者參考一篇透過三種指標綜合所打造的交易策略Trading Stocks using Bollinger Bands, Keltner Channel, and RSI in Python範例改寫為C#版本當作台指期5分K交易進出邏輯。進場條件為布林通道上下緣超過肯特納通道上下緣,而且RSI相對強弱指標需要超過70或是低於35。出場條件則是布林通道上下緣低於肯特納通道上下緣或是RSI相對強弱指標回到70至35中間震盪。進出場濾網則是加上了一個ATR價格波動。簡單說就是把肯特納通道當作震盪區間,一旦突破這個區間就開始順勢買多或是賣空,回到這個區間就平倉。

實作完這個簡易的策略之後,當然就是要開始跑回測。回測數據要去哪裡找呢? 還好可以透過群益API下載過去一年份的1分K歷史資料當作回測數據,但是一年份的資料代表性其實是存疑的,不過筆者也沒甚麼好方法,也懶得去撈其他來源的歷史資料,還要驗證資料正確性與格式轉換,只好死馬當活馬醫,透過模擬現在系統時間的方式去餵1分K資料給這個策略執行,以一口大台的成本得到的結果扣除手續費大概就是一千點上下,平均每個工作天可以賺個五點,換算大台指就是台幣一千塊錢,最高連續虧損會落在一百多點,也就是兩萬多塊台幣。老實說,執行這個策略不如不要執行,去超商老老實實的打工比較實在,但是滿足了技術宅探索量化交易的願望。

跑完回測,至少看到期望值是正的。接下來就是模擬下單,到這邊就會發現滑價的問題,用限價去買賣成交常常不成功,只好透過範圍市價的方式交易,然後開始祈禱不要賠太多。以下是群益API設定範圍市價的方法。

        public int OrderFuture(string strStockNo, string strPrice, int nQty, short nBidAsk, short type, ref string strMessage)
{
FUTUREORDER pOrder = new FUTUREORDER()
{
bstrFullAccount = m_UserAccount,
bstrPrice = "P", // 委託價格,「M」表示市價,「P」表示範圍市價
bstrStockNo = strStockNo,
nQty = nQty,
sTradeType = 1, //0:ROD 1:IOC 2:FOK
sBuySell = nBidAsk, //0:買進 1:賣出
sDayTrade = 0, //當沖0:否 1:是,可當沖商品請參考交易所規定。
sNewClose = type, //新平倉,0:新倉 1:平倉 2:自動{新期貨、選擇權使用}
sReserved = 0 //{期貨委託SendFutureOrderCLR適用}盤別,0:盤中(T盤及T+1盤);1:T盤預約
};

m_nCode = OnFutureOrderSignal(m_strLoginID, false, pOrder, ref strMessage);

return m_nCode;
}

在連續跑了幾星期的模擬下單後發現,好像沒有賠太多,運氣好的時候,還真的有賺一些。於是筆者捏緊了懶趴心一橫就開始實單交易,果然不出意外的話就要出意外了,實單交易一直連續賠錢到現在,也不知道回測中的賺錢時間甚麼時候會到來。真正達到第一次量化交易投資就賠錢的境界。

做個總結,因為本文所提及的交易策略較為粗陋,大部分時間都是在等待,也沒有順勢加碼的策略(其實筆者本身也沒有加碼的本錢),所以獲利的空間相當有限,另外台股特性本來就是震盪居多,波段走勢較少,也導致這個策略需要更多的耐心與信心去執行。好處就是電腦自動執行,萬一有個波段行情的時候,電腦程式能夠自行去下單交易,壞處就是獲利期望值太少,甚至扣除手續費與滑價問題的話,還會賠錢,不如其他長期持有的策略賺得還比較多。筆者自己還是趁工作閒暇之餘,找尋其他交易策略,希望有朝一日能夠真正實現財富自由的願望。






留言
avatar-img
留言分享你的想法!
Simon Liao-avatar-img
2023/08/13
失敗是正常的,因為程式的K Bar 計算不正確,就會影響整個交易結果 private IEnumerable generate_OHLCBar(IEnumerable ticks, long barSizeInTicks) { TimeSpan natural_time = new TimeSpan(8, 45, 0); var bars = from tick in ticks let barIndexForDay = Math.Floor(tick.Timestamp.TimeOfDay.Subtract(natural_time).TotalSeconds / barSizeInTicks) let barBeginDateTime = tick.Timestamp.Date.Add(natural_time).AddSeconds(barIndexForDay * barSizeInTicks) let barEndDateTime = tick.Timestamp.Date.Add(natural_time).AddSeconds((barIndexForDay + 1) * barSizeInTicks) group tick by new { barBeginDateTime, barEndDateTime, tick.Symbol } into tickGroup orderby tickGroup.Key.barBeginDateTime 你有空再確認一下,每個時間區間是否是你要的結果
Colchicine-avatar-img
2023/07/15
Cool 寫得真好,我也是過來人,有機會交流交流Best Regards,Colchicine
avatar-img
Gary Hu的沙龍
4會員
11內容數
Gary Hu的沙龍的其他內容
2025/04/14
從2023年之前,美股會直接預扣30% 股息預扣稅率,但是在2023年通過台美稅務協定後,你想在美國券商(例如 TD Ameritrade、Firstrade、Charles Schwab 等)享有台美稅務協定下的21% 股息預扣稅率,關鍵就在於正確填寫並提交一份W-8BEN 表格。 以下是步
Thumbnail
2025/04/14
從2023年之前,美股會直接預扣30% 股息預扣稅率,但是在2023年通過台美稅務協定後,你想在美國券商(例如 TD Ameritrade、Firstrade、Charles Schwab 等)享有台美稅務協定下的21% 股息預扣稅率,關鍵就在於正確填寫並提交一份W-8BEN 表格。 以下是步
Thumbnail
2024/12/21
小弟走跳江湖多年,也累績了一些職場心得,在年底轉職熱門時刻,希望能夠幫助到一些有緣人。
2024/12/21
小弟走跳江湖多年,也累績了一些職場心得,在年底轉職熱門時刻,希望能夠幫助到一些有緣人。
2024/10/13
本地端生成式AI工具LM Studio安裝介紹,包含如何手動載入AI模型的技巧。
Thumbnail
2024/10/13
本地端生成式AI工具LM Studio安裝介紹,包含如何手動載入AI模型的技巧。
Thumbnail
看更多
你可能也想看
Thumbnail
沙龍一直是創作與交流的重要空間,這次 vocus 全面改版了沙龍介面,就是為了讓好內容被好好看見! 你可以自由編排你的沙龍首頁版位,新版手機介面也讓每位訪客都能更快找到感興趣的內容、成為你的支持者。 改版完成後可以在社群媒體分享新版面,並標記 @vocus.official⁠ ♥️ ⁠
Thumbnail
沙龍一直是創作與交流的重要空間,這次 vocus 全面改版了沙龍介面,就是為了讓好內容被好好看見! 你可以自由編排你的沙龍首頁版位,新版手機介面也讓每位訪客都能更快找到感興趣的內容、成為你的支持者。 改版完成後可以在社群媒體分享新版面,並標記 @vocus.official⁠ ♥️ ⁠
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
網路上你有沒有遇到所謂投資達人,會教很多選股技術分析或基本面分析秘招,例如:技術線型三角收斂準備上飆、連兩年EPS成長、股息殖利率連續10年6%以上...,又有一派是消息面,例如:新創股明年有一個AI題材,籌碼面已經被主力大戶鎖住,結論也是股價準備上飆...,你是不是被這種網路資訊轟炸到不知該相信誰
Thumbnail
網路上你有沒有遇到所謂投資達人,會教很多選股技術分析或基本面分析秘招,例如:技術線型三角收斂準備上飆、連兩年EPS成長、股息殖利率連續10年6%以上...,又有一派是消息面,例如:新創股明年有一個AI題材,籌碼面已經被主力大戶鎖住,結論也是股價準備上飆...,你是不是被這種網路資訊轟炸到不知該相信誰
Thumbnail
學習程式交易對於想要投資的人來說是一個很好的選擇。儘管初學程式語言可能有點困難,但這是可以克服的。程式交易可以幫助你維持一致的交易紀律,並且有效地克服心理因素的影響。當你無法時時刻刻關注市場時,程式交易也能夠監控你的交易部位。所以,學習程式交易不僅是一種增加技能的方式,更是一種提高投資成功率的方法。
Thumbnail
學習程式交易對於想要投資的人來說是一個很好的選擇。儘管初學程式語言可能有點困難,但這是可以克服的。程式交易可以幫助你維持一致的交易紀律,並且有效地克服心理因素的影響。當你無法時時刻刻關注市場時,程式交易也能夠監控你的交易部位。所以,學習程式交易不僅是一種增加技能的方式,更是一種提高投資成功率的方法。
Thumbnail
交易計畫是投資操作中最需要重視的事情,一直以來本人都是靈感交易,參考幾個指標跟看財經分析之後就自以為是的買進賣出,結果不用說,韭菜就是韭菜。
Thumbnail
交易計畫是投資操作中最需要重視的事情,一直以來本人都是靈感交易,參考幾個指標跟看財經分析之後就自以為是的買進賣出,結果不用說,韭菜就是韭菜。
Thumbnail
散戶,你還在“聽聲辨位”嗎? 你是懷著賺零用錢或者財富自由的目的來到投資或者投機這條路呢?你開始了嗎?賺到錢了嗎? 有人,他是每天抄寫股價的嗎?每天抄寫,已經抄寫了四十幾年了,抄出盤感,至今還在抄! 有人,每天從開盤8:45就開始操盤,一直到1:45收盤,才離開操盤室,然後每天還做功課,選出隔天想要
Thumbnail
散戶,你還在“聽聲辨位”嗎? 你是懷著賺零用錢或者財富自由的目的來到投資或者投機這條路呢?你開始了嗎?賺到錢了嗎? 有人,他是每天抄寫股價的嗎?每天抄寫,已經抄寫了四十幾年了,抄出盤感,至今還在抄! 有人,每天從開盤8:45就開始操盤,一直到1:45收盤,才離開操盤室,然後每天還做功課,選出隔天想要
Thumbnail
我們不可能在任何時刻都跟機械人一樣理性地做出判斷,所以我們需要一套準則來告訴你,這個時間點或是這個當下,你該做些什麼,這套準則就是所謂的【交易策略】。
Thumbnail
我們不可能在任何時刻都跟機械人一樣理性地做出判斷,所以我們需要一套準則來告訴你,這個時間點或是這個當下,你該做些什麼,這套準則就是所謂的【交易策略】。
Thumbnail
請先看完這篇兩年半前在PTT的舊文章,主內容跟下面的推文更新都要看,因為這篇舊文值得參考的資訊除了籌碼以外,還有很多點。 籌碼到底有沒有參考價值? 前一篇文章留言區提到的夢境內容,其實也只是PTT這篇鄉民認為是瞎扯的文章內容的實戰範例而已。
Thumbnail
請先看完這篇兩年半前在PTT的舊文章,主內容跟下面的推文更新都要看,因為這篇舊文值得參考的資訊除了籌碼以外,還有很多點。 籌碼到底有沒有參考價值? 前一篇文章留言區提到的夢境內容,其實也只是PTT這篇鄉民認為是瞎扯的文章內容的實戰範例而已。
Thumbnail
嗨各位,我又來了 繼上次跟大家分享的三點,在文字上有些強硬、誤會,用類似訓人的方式表達,這不是我的本意,因為一直以來就有人說過我的文章、文字太生硬(沒有顏文字空虛又不可愛ಠ_ಠ)才導致有這樣的誤會,請大家多包容,我也會努力呈現出口語化的表達方式,讓大家不要那麼有敵意😣😣 在下面跟各位介紹進入
Thumbnail
嗨各位,我又來了 繼上次跟大家分享的三點,在文字上有些強硬、誤會,用類似訓人的方式表達,這不是我的本意,因為一直以來就有人說過我的文章、文字太生硬(沒有顏文字空虛又不可愛ಠ_ಠ)才導致有這樣的誤會,請大家多包容,我也會努力呈現出口語化的表達方式,讓大家不要那麼有敵意😣😣 在下面跟各位介紹進入
Thumbnail
在先前的教學中,我們都是透過已知的歷史資料來進行數據的分析,並且找尋到適合的交易策略,不過要如何實際交給程式監測跟下單呢?這部分就是我們接下來最後3天要來教學的地方了,而今天我們就先來學習如何取得股價目前的即時資訊吧!!
Thumbnail
在先前的教學中,我們都是透過已知的歷史資料來進行數據的分析,並且找尋到適合的交易策略,不過要如何實際交給程式監測跟下單呢?這部分就是我們接下來最後3天要來教學的地方了,而今天我們就先來學習如何取得股價目前的即時資訊吧!!
Thumbnail
1.買在最低,賣在最高 2.賺到一點錢就跑,賠了錢就想凹回來 3.對行情有一定的預期 〔投資技巧〕:設定進出場SOP,下回分享
Thumbnail
1.買在最低,賣在最高 2.賺到一點錢就跑,賠了錢就想凹回來 3.對行情有一定的預期 〔投資技巧〕:設定進出場SOP,下回分享
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News