まえがき
こんにちは、さつま芋です。
有名なトリックアートですが、つくづく不思議なものだと思いませんか。
感覚の優れた人ならば正しく見抜けるのでしょうか。
いずれにしても、人の感覚とは不思議なものです。
奇しくも、FXもトリック満載です。
中でも、最大のトリックはスプレッドだと思います。
機械的に検証したバックテスト結果を紹介しながら説明してみます。
バックテスト
平均足を使ったトレードのバックテストをしました。
2023年4月の一ヶ月分のドル円(USDJPY)平均足(5分)を使い、転換でエントリーし、損切り10pips、利確10pipsとする機械的なシミュレーションをしました。
結果を見る前に、少し想像してみてください。
ローソク足よりもトレンドを視認しやすいと言われる、あの平均足です。
忠実に平均足の転換確定でエントリーし、決まった値幅で機械的にエグジットしたとき、何だか勝てそうな気がしませんか。
それでは資金の推移を見てみましょう。
最低取引量の1000通貨に固定したときの資金推移です。
いちおう標準的な国内FX業者のスプレッド0.5pipsを考慮しています。
総取引数533回、勝率50.46%で最終損益は-2165円でした。
仮にスプレッドが0pipsのとき、最終損益は+500円となりました。
スプレッドコスト
ちょうど黒い折れ線と橙の折れ線の間がスプレッドの影響を表しています(再掲)。
決済までの10pipsの値幅に対して、僅か0.5pipsのスプレッドでも相当の影響があったことが伝わるでしょうか。
実際、指値注文をしていてもスリッページは起こるので、スキャルピングトレードは非常に不利な取引形態だと言えます。
わざわざ不利な状況でトレードしないという判断もトレード力かもしれません。
あとがき
価格データはHistData.comからダウンロードし、バックテストはRで行いました。
# Read data
fx <- read.csv("DAT_MT_USDJPY_M1_202304.csv", header = FALSE)# Set column names
colnames(fx) <- c("date", "time", "open", "high", "low", "close", "volume")# Convert date and time columns to POSIXct
fx$date <- as.POSIXct(paste(fx$date, fx$time), format = "%Y.%m.%d %H:%M", tz="UTC")
library(lubridate)
fx$date <- with_tz(fx$date, tz="Asia/Tokyo")library(xts)
# Create xts object
fx_xts <- as.xts(fx[, 3:6], order.by = fx$date)# Calculate Heikin-Ashi candles
fx_xts$ha_close <- (fx_xts[, 1] + fx_xts[, 2] + fx_xts[, 3] + fx_xts[, 4]) / 4
fx_xts$ha_open <- (lag(fx_xts[, 1], 1) + lag(fx_xts[, 4], 1)) / 2
fx_xts$ha_high <- pmax(fx_xts[, 2], pmax(fx_xts[, 5], fx_xts[, 6]))
fx_xts$ha_low <- pmin(fx_xts[, 3], pmin(fx_xts[, 5], fx_xts[, 6]))
fx_xts <- na.omit(fx_xts)# Create Heikin-Ashi chart
fx_xts_heikin <- fx_xts[, c("ha_open", "ha_high", "ha_low", "ha_close")]
colnames(fx_xts_heikin) <- c("open", "high", "low", "close")# Load quantmod library
library(quantmod)# Create Heikin-Ashi chart
chartSeries(fx_xts_heikin, theme = "white", type = "candlestick", na.rm = TRUE, subset = "last 3 hours")# Create OHLC chart for 4-hour periods
fx_xts_M5 <- to.period(fx_xts, period = "minutes", k = 5)
colnames(fx_xts_M5) <- c("open", "high", "low", "close")# Calculate Heikin-Ashi candles
fx_xts_M5$ha_close <- (fx_xts_M5[, 1] + fx_xts_M5[, 2] + fx_xts_M5[, 3] + fx_xts_M5[, 4]) / 4
fx_xts_M5$ha_open <- (lag(fx_xts_M5[,1], 1) + lag(fx_xts_M5[,4], 1)) / 2
fx_xts_M5$ha_high <- pmax(fx_xts_M5[, 2], pmax(fx_xts_M5[,5], fx_xts_M5[,6]))
fx_xts_M5$ha_low <- pmin(fx_xts_M5[, 3], pmin(fx_xts_M5[,5], fx_xts_M5[,6]))
fx_xts_M5 <- na.omit(fx_xts_M5)# Create Heikin-Ashi chart
fx_xts_M5_heikin <- fx_xts_M5[, c("ha_open", "ha_high", "ha_low", "ha_close")]
colnames(fx_xts_M5_heikin) <- c("open", "high", "low", "close")# Create OHLC chart
chartSeries(fx_xts_M5_heikin, theme = "white", type = "candlestick", na.rm = TRUE, subset = "last 3 weeks")
entry_price <- NA
position <- 0
fx_xts_M5$Position <- NA
profit <- 0
profit2 <- 0for(i in 1:nrow(fx_xts_M5)){
if(position==0){
if(as.numeric(fx_xts_M5$ha_close[i]) > as.numeric(fx_xts_M5$ha_open[i])){
entry_price <- as.numeric(fx_xts_M5$close[i])
position <- 1
fx_xts_M5$Position[i] <- 1
}
else if(as.numeric(fx_xts_M5$ha_close[i]) < as.numeric(fx_xts_M5$ha_open[i])){
entry_price <- as.numeric(fx_xts_M5$close[i])
position <- -1
fx_xts_M5$Position[i] <- -1
}
}
else if(position==1){
if(as.numeric(fx_xts_M5$ha_low[i])-entry_price < -0.1){
position <- 0
profit[i] <- -0.105*1000
profit2[i] <- -0.1*1000
entry_price <- NA
}
else if(as.numeric(fx_xts_M5$ha_high[i])-entry_price > 0.1){
position <- 0
profit[i] <- 0.095*1000
profit2[i] <- 0.1*1000
entry_price <- NA
}
}
else if(position==-1){
if(as.numeric(fx_xts_M5$ha_high[i])-entry_price > 0.1){
position <- 0
profit[i] <- -0.105*1000
profit2[i] <- -0.1*1000
entry_price <- NA
}
else if(as.numeric(fx_xts_M5$ha_low[i])-entry_price < -0.1){
position <- 0
profit[i] <- 0.095*1000
profit2[i] <- 0.1*1000
entry_price <- NA
}
}
cumsumprofit <- cumsum(na.omit(profit))
cumsumprofit2 <- cumsum(na.omit(profit2))
}plot(cumsumprofit, type="l", col="black", xlab="回数", ylab="資金")
lines(cumsumprofit2, col="orange")
legend("bottomleft", c("Spread 0.5", "No spread"), col=c("black", "orange"), lty=1)library(dplyr)
sum(na.omit(profit)) %>% print()
sum(na.omit(profit2)) %>% print()
wins <- sum(na.omit(profit>0)) %>% print()
loses <- sum(na.omit(profit<0)) %>% print()
win_rate <- (100*wins/(wins+loses) ) %>% print()
スキャルピングは「資金効率がいい」とか「窓開けリスクがない」とか「経験を積みやすい」とか言われるのですが、致命的にスプレッドコストが嵩みます。
加えて、FX業者からも嫌われるらしいですし、これは本当にスプレッドを正しく見抜けているのでしょうか。
以上、さつま芋でした。