时间序列分析day01-前置内容

本文回顾了R语言的基本操作,包括向量和矩阵的创建与运算。介绍了如何利用matrix()函数生成矩阵,并展示了通过ts()函数转换向量为时间序列对象的过程。此外,还探讨了使用plot()函数进行数据可视化,包括绘制普通图像和时间序列图像。最后,应用par()函数实现多图并排展示。


心得体会

本次主要学习了时间序列分析所需要的前置内容,复习了R语言的基础操作。

在这里感谢datawhale开源社区的小伙伴们给予的学习帮助,今后的学习也要一样加油呀


提示:以下是本篇文章正文内容

R语言基础

向量与矩阵

R 语言中可以通过 c(...) 来声明一个向量,例如 x = ( 1 , 2 , 3 , 4 , 5 ) \boldsymbol{x} = (1, 2, 3, 4, 5) x=(1,2,3,4,5) 可以通过 x <- c(1, 2, 3, 4, 5) 来声明。

对两个长度相等的向量进行四则运算的效果是向量中的每一个元素都与另一个向量中的每一个元素进行四则运算。而一个向量与一个数进行四则运算的效果是该向量中的所有元素都与这个数进行四则运算。如:

> x <- c(1, 2, 3, 4, 5)
> y <- c(1, 2, 3, 4, 5)
> x+y
[1]  2  4  6  8 10
> x+1
[1] 2 3 4 5 6
> x
[1] 1 2 3 4 5

矩阵

R 语言中可以通过 matrix() 函数来创建矩阵。matrix() 的原型为 matrix(data=NA, nrow=1, ncol=1, byrow=FALSE, dinames=NULL) 其中:

  • data : 矩阵的元素,通常为向量。
  • nrowncol : 设定矩阵的行数和列数,一般只需设定其一,另一个会根据数据长度算出。
  • byrow : 设定矩阵的填充方式,值为 TRUE 时按行填充。默认为 FALSE ,即按列填充。

通过 matrix() 创建矩阵的例子如下:

> mat1 <- matrix(1:6, nrow=2) # 元素为1到6, 两行,按列填充
> mat1
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

> mat2 <- matrix(1:6, nrow=2, byrow=TRUE)
> mat2
     [,1] [,2] [,3]
[1,]    1    2    3
[2,]    4    5    6

此外还可以使用 dim() 通过向量来创建矩阵,例如:

> mat3 <- 1:6
> dim(mat3) <- c(3, 2) # 将元素为1到6变为3行2列的矩阵
> mat3
     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

生成时间序列

通过 ts() 函数可以将一个向量或矩阵转成一个一元或多元的时间序列(ts)对象,ts() 函数的原型为:ts(data = NA, start = 1, end = numeric(0), frequency = 1, deltat = 1, ts.eps = getOption("ts.eps"), class, names)。其中:

  • data 要生成时间序列的向量或矩阵。
  • start 第一个观测值的时间。
  • end 最后一个观测值的时间。
  • frequency 单位时间内观测值的频数。
  • deltat 两个观测值之间的时间间隔。
  • ts.eps 序列之间的误差限。若序列之间的频率差异小于 ts.eps 则认为这些序列的频率相等。
  • class 对象的类型。一元序列默认为 ts,多元序列默认为 c("mts", "ts")
  • names 给出多元序列中每个一元序列的名称,默认为 Series 1, Series 2, ...

下面是一个例子:

> ts(1:26, start = 1986)
Time Series:
Start = 1986 
End = 2011 
Frequency = 1 
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
[18] 18 19 20 21 22 23 24 25 26

画图

R 语言中可以直接使用 plot() 函数来绘制图像,例如:

> x <- rnorm(10)
> x
 [1] -1.1297214 -0.1540311  1.9312926  0.2565608  0.1138023 -0.1129219
 [7]  0.2522398 -0.4107701 -0.3514792  0.4254152
> plot(x)

在这里插入图片描述
还可以直接绘制时间序列的图像:

> plot(ts(x))

在这里插入图片描述
为了将多幅图画在一起,可以使用 par() 函数:

> op <- par(mfrow=c(2, 1), mar=c(5, 4, 2, 2) + .1) # mfrow 指定了图像矩阵为两行一列,即画两幅图,每行一幅;mar 指定了图像的边界,分别是下、左、上、右,可以根据喜好指定
> plot(ts(x))
> acf(x, main = "") # 计算 acf 函数

在这里插入图片描述


参考资料:

开源仓库:https://github.com/datawhalechina/team-learning-data-mining/tree/master/TimeSeries

//+------------------------------------------------------------------+ //| FixedFiboDayRangeStrategy_v3.mq5 | //| Copyright 2023, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.01" #property description "修复版:基于斐波那契扩展的交易策略" #property description "已解决所有编译错误和逻辑问题" // 输入参数 input double LotSize = 0.1; // 固定交易手数 input int MagicNumber = 2023; // EA唯一标识 input int StopLossPips = 50; // 止损点数 input color FibColor = clrDodgerBlue; // 斐波那契线颜色 input string FibLevels = "0,23.6,38.2,50,61.8,100,138.2,161.8"; // 斐波那契水平 input int CloseHour = 22; // 平仓时间(小时) input int CloseMinute = 0; // 平仓时间(分钟) // 全局变量 double prevHigh, prevLow; double fibLevelsArray[]; int fibLevelsCount; datetime lastTradeDay; string objPrefix = "Fibo_"; //+------------------------------------------------------------------+ //| 前置声明 | //+------------------------------------------------------------------+ void CheckNewTradingDay(); void LoadPreviousDayLevels(); void DrawFibonacciLevels(); bool HasOpenPositions(); void CheckEntrySignals(); void CheckCloseConditions(); void CloseAllPositions(); bool OpenTrade(ENUM_ORDER_TYPE orderType, double sl, double tp); //+------------------------------------------------------------------+ //| EA初始化函数 | //+------------------------------------------------------------------+ int OnInit() { // 修复1: 正确解析斐波那契水平 string levelsArray[]; fibLevelsCount = StringSplit(FibLevels, ',', levelsArray); ArrayResize(fibLevelsArray, fibLevelsCount); for(int i = 0; i < fibLevelsCount; i++) { fibLevelsArray[i] = StringToDouble(levelsArray[i]); } // 初始化交易日 lastTradeDay = 0; // 获取前一日高低点 LoadPreviousDayLevels(); // 绘制斐波那契水平线 DrawFibonacciLevels(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| EA终止函数 | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // 删除所有斐波那契对象 ObjectsDeleteAll(0, objPrefix); Comment(""); } //+------------------------------------------------------------------+ //| 主执行函数 | //+------------------------------------------------------------------+ void OnTick() { // 检查新交易日 CheckNewTradingDay(); // 检查平仓条件 CheckCloseConditions(); // 检查开仓信号 if(!HasOpenPositions()) { CheckEntrySignals(); } } //+------------------------------------------------------------------+ //| 修复2: 获取前一日高低点 | //+------------------------------------------------------------------+ void LoadPreviousDayLevels() { datetime endTime = iTime(_Symbol, PERIOD_D1, 1); datetime startTime = endTime - PeriodSeconds(PERIOD_D1); MqlRates rates[]; int copied = CopyRates(_Symbol, PERIOD_D1, startTime, endTime, rates); if(copied > 0) { prevHigh = rates[0].high; prevLow = rates[0].low; Comment("前一日高低点: High=", prevHigh, " Low=", prevLow); } else { Print("加载前一日数据失败! 错误: ", GetLastError()); } } //+------------------------------------------------------------------+ //| 修复3: 检查新交易日函数 | //+------------------------------------------------------------------+ void CheckNewTradingDay() { MqlDateTime currentTime; TimeCurrent(currentTime); MqlDateTime lastTradeTime; TimeToStruct(lastTradeDay, lastTradeTime); // 修复9: 正确使用TimeDay函数 if(currentTime.day != lastTradeTime.day) { LoadPreviousDayLevels(); DrawFibonacciLevels(); lastTradeDay = TimeCurrent(); } } //+------------------------------------------------------------------+ //| 修复4: 绘制斐波那契水平线 | //+------------------------------------------------------------------+ void DrawFibonacciLevels() { // 删除旧对象 ObjectsDeleteAll(0, objPrefix); double range = prevHigh - prevLow; // 绘制斐波那契水平线 for(int i = 0; i < fibLevelsCount; i++) { double levelValue = fibLevelsArray[i]; double priceLevel = prevLow + (range * levelValue / 100.0); string objName = objPrefix + "Level_" + DoubleToString(levelValue, 1); if(!ObjectCreate(0, objName, OBJ_HLINE, 0, 0, priceLevel)) { Print("创建水平线失败: ", GetLastError()); continue; } ObjectSetInteger(0, objName, OBJPROP_COLOR, FibColor); ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DASHDOT); ObjectSetInteger(0, objName, OBJPROP_WIDTH, 1); ObjectSetInteger(0, objName, OBJPROP_BACK, true); string text = DoubleToString(levelValue, 1) + "%"; ObjectSetString(0, objName, OBJPROP_TEXT, text); } } //+------------------------------------------------------------------+ //| 修复5: 检查开仓信号 | //+------------------------------------------------------------------+ void CheckEntrySignals() { // 修复4: 声明bid和ask变量 double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double current = (bid + ask) / 2.0; double range = prevHigh - prevLow; double threshold = range * 0.05; // 计算关键斐波那契水平 double fib50 = prevLow + range * 0.5; double fib61 = prevLow + range * 0.618; double fib38 = prevLow + range * 0.382; MqlRates currentBar[]; CopyRates(_Symbol, PERIOD_CURRENT, 0, 1, currentBar); // 多头信号 if(current > prevHigh && current < (fib50 + threshold) && current > fib38) { if(currentBar[0].close < currentBar[0].open) { double sl = MathMin(prevLow, fib38); double tp = fib61; OpenTrade(ORDER_TYPE_BUY, sl, tp); } } // 空头信号 else if(current < prevLow && current > (fib50 - threshold) && current < fib61) { if(currentBar[0].close > currentBar[0].open) { double sl = MathMax(prevHigh, fib61); double tp = fib38; OpenTrade(ORDER_TYPE_SELL, sl, tp); } } } //+------------------------------------------------------------------+ //| 修复6: 开仓函数(解决枚举转换错误) | //+------------------------------------------------------------------+ bool OpenTrade(ENUM_ORDER_TYPE orderType, double sl, double tp) { MqlTradeRequest request; MqlTradeResult result; // 修复4: 声明bid和ask变量 double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // 修复3: 正确设置枚举值 request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = LotSize; request.magic = MagicNumber; request.type = orderType; request.price = (orderType == ORDER_TYPE_BUY) ? ask : bid; // 设置止损止盈 if(sl > 0) request.sl = NormalizeDouble(sl, _Digits); if(tp > 0) request.tp = NormalizeDouble(tp, _Digits); // 发送交易请求 if(!OrderSend(request, result)) { Print("开仓失败: ", EnumToString(orderType), " 错误=", GetLastError()); return false; } Print("开仓成功: ", EnumToString(orderType), " 价格=", request.price); return true; } //+------------------------------------------------------------------+ //| 修复7: 检查平仓条件 | //+------------------------------------------------------------------+ void CheckCloseConditions() { MqlDateTime now; TimeCurrent(now); // 修复8: 正确使用括号表达式 if((now.hour == CloseHour && now.min >= CloseMinute) || (now.hour > CloseHour)) { CloseAllPositions(); } } //+------------------------------------------------------------------+ //| 修复8: 平仓所有持仓 | //+------------------------------------------------------------------+ void CloseAllPositions() { for(int i = PositionsTotal()-1; i >= 0; i--) { if(PositionGetTicket(i)) { ulong ticket = PositionGetInteger(POSITION_TICKET); if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == _Symbol) { MqlTradeRequest request; MqlTradeResult result; // 修复3: 正确设置枚举值 request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = PositionGetDouble(POSITION_VOLUME); request.magic = MagicNumber; request.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY; request.position = ticket; if(!OrderSend(request, result)) { Print("平仓失败: 错误=", GetLastError()); } else { Print("已平仓: ", PositionGetString(POSITION_SYMBOL)); } } } } } //+------------------------------------------------------------------+ //| 检查持仓状态 | //+------------------------------------------------------------------+ bool HasOpenPositions() { for(int i = 0; i < PositionsTotal(); i++) { if(PositionGetTicket(i)) { if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue; if(PositionGetInteger(POSITION_MAGIC) == MagicNumber) { return true; } } } return false; }你写的这个策略不能成交
07-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值