市场模拟(第 20 部分):SQL 入门(三)
概述
大家好,这是关于构建复制/模拟系统的系列文章的又一篇。
在本文中,我们将开始探讨一个相当复杂的话题。但如果你能理解我们接下来要讲的内容,你的职业生涯将会有显著的提升。这并非易事。尽管如此,我们还是会尽量用最简单的方式去解释。
准备脚本
在上一篇文章《市场模拟(第 19 部分):SQL 入门(二)》中,我们介绍了如何使用脚本在数据库中添加、修改甚至删除记录。然而,为了继续进行解释,我们需要先进行一个简单的数据库设置。这将使你能够真正理解将要解释的内容。
尽管我们可以使用一个包含大约 10 条记录的数据库,但当我们使用一个包含超过 15000 条记录的文件时,理解起来会更容易。也就是说,如果我们试图手动创建这样一个数据库,这项任务将十分艰巨。然而,即便出于教育目的,也很难找到这样一个可供下载的数据库。但其实没有必要这么做:我们可以使用 MetaTrader 5 来生成它。它或许并不完美,但至少会包含大量记录,而这正是我们所需要的。
为了理解我们将如何使用 MetaTrader 5 来创建数据库并探讨这个主题,我们需要稍微回顾一下过去。
有些人甚至一些小型组织都将 Excel 作为数据库来使用。你们中的许多人可能不相信这一点,或者可能没有注意到这种情况的发生。而且不仅仅是 Excel,还有其他程序也以这种方式使用。但就目前而言,我们将仅限于使用 Excel。当我们使用 Excel 处理数据库时,功能区上会出现一个附加选项卡。下图展示了所指内容。

为了让这个标签页显示出来,我们需要做几件事。其中一种,或许也是最简单的一种,就是打开一个具有特定格式或结构的文件。这是在下图所示的位置完成的。

请记住,我们展示的是其中一种方法,但并非唯一方法。现在问题来了:我们这里要用什么类型的文件?你极有可能会用到不同类型的文件。我说这话的意思是,文件的内部结构可以是任何形式,但为了简化问题并更好地理解材料,让我们继续讨论 MetaTrader 5。在下图中,我们就能明白我的意思了。

请注意,我们已向交易服务器发送请求,以获取某一交易品种在特定日期的全部逐笔数据(ticks)。上图所展示的正是来自数据库的一组信息。然而,在这个窗口中,我们无法像使用专用软件时那样操作数据。然而,我们可以将此信息导出到文件中。可以是 CSV 格式。
将该文件保存到本地磁盘后,我们就可以在处理数据库文件的程序中使用它了。但是,在我们开始处理文件内容并将其解释为数据表之前,需要先将其转换为数据库,这一点很重要。这就是过程的奇妙之处,而这正是我们想要达到的目标。
工作台外的首次接触
然后,将上图所示的信息保存到文件中后,我们可以先将其导入到 Excel 中。因此,Excel 处理文件的方式将不再是你想象中的那样。Excel 实际上会将文件转换为等效的数据库。因此,Excel 界面将发生变化,如下所示:

好吧,你可能会认为在这里你可以像使用 SQL 命令一样工作。事实上,当使用 Excel 或其他能够提供一定程度的数据库访问权限的程序时,情况并非完全如此。尽管你实际上可以在这里做很多事情,但这种体验与使用纯 SQL 的体验相比,还是相去甚远。所以,我们还是别用 Excel 了,换个方向吧。这是必要的,这样我们才能理解接下来要解释的命令。
使用 MetaEditor 浏览数据库
你很可能认为我们遇到了一个大问题,因为在大多数情况下, MetaTrader 5 下载并以 CSV 格式保存的文件可能会占用数兆字节的空间。而将这样的数据转换为可接受的格式(以便能对下载的数据使用 SQL 查询),似乎是一项艰巨的任务,只有高超的计算机高手才能完成。然而,事实是,如果你不了解手头的工具,即使解决方案就在眼前,你也总是会遇到问题需要解决。
因此,在不使用编程的情况下,将 MetaTrader 5 下载的所有数据转换为更方便格式的最简单方法就是使用 MetaEditor。这将有效地将下载的 CSV 文件转换为真正的数据库文件。但具体该怎么做呢?如何使用 MetaEditor 将 MetaTrader 5 保存的 CSV 文件转换为数据库文件?这看起来似乎非常困难,但亲爱的读者们,其实远非如此。关键在于了解你手中掌握的是哪一种工具。
首先,我们先创建一个全新的、完全空白的数据库。我们已经解释过如何使用 MetaEditor 来完成这项操作。创建这个数据库文件后,我们需要执行以下步骤。
首先,选择下图所示的选项:

此选项允许您将表导入数据库。请记住,表是记录的集合。由于 CSV 文件也是记录的集合,因此我们将其像表一样导入。选择所需选项后,将打开一个窗口,您需要在其中配置 MetaEditor 的数据导入设置以创建最终表。下图可以看到这个窗口。

为了尽可能简化操作,我们将 CSV 文件放在了 MQL5 目录中。然而,归根结底,重要的是我们要选择正确的文件。然而,如果我们如上图所示,只是简单地选择文件,并立即点击“打开”按钮,MetaEditor 将不会显示任何响应。这是因为我们仅选择了该文件,但尚未导入。必须在同一窗口中配置一些额外的设置。这些设置中的每一个都取决于具体情况 — 没有严格的规则。
你至少应该对要导入的文件内容有一个大致的了解。仅仅打开 MetaEditor,请求数据导入,然后指望它能自行识别文件内容,这是没有用的。实际并不是这样工作的。所以,我们需要配置的第一项是数据分隔符。请记住,这些数据是由 MetaTrader 5 生成的。如果您没有更改文件格式,则使用的分隔符是制表符。调整该设置后,界面将显示如下图所示的效果。

好的,这是我们需要配置的第一个项目。现在还有一点需要考虑,因为你刚刚下载了文件,并且正准备将其导入 MetaEditor。这涉及到要使用的表的名称。在这个阶段,许多人可能会感到困惑,因为在 MetaEditor 的数据库中,我们还没有包含任何表。从上面的图片可以看出,在请求文件导入时没有指定任何表。
那么,我们应该提供什么信息作为表名呢?我们只需指定创建表时将为其分配的名称。这就是为什么我们建议使用一个完全干净的文件 — 这样可以使这一步骤更容易理解。接下来,我们输入表名,如下图所示。

您可以给它取任何名字。之后,我们就可以点击“打开”按钮了。请记住,根据导入文件的内容,此处可能还需要进一步配置其他选项。然而,由于我们刚刚从 MetaTrader 5 下载了文件,并且正在使用 MetaEditor 导入该文件,因此这些步骤足以满足我们的需求。
我们点击“打开”后,就需要完全忘记之前在 Excel 中使用同一文件时可能看到的内容。这里的一切与你阅读这些关于数据库的文章之前所看到的内容都将大不相同。因此,当我们查看 MetaEditor 屏幕时,首先会看到以下图像。

很好,如果看到此内容,则表示 MetaEditor 已将 CSV 文件转换为名为 MT5_Tutor.db 的数据库中的表。很可能,此时此刻,你可能会感到完全困惑,不明白刚刚发生了什么。但让我们来详细分析一下,因为这是一个重要的概念。
MetaTrader 5 下载的所有信息 — 即我们在特定日期向服务器请求某个交易品种的数据时 — 已不再是一堆杂乱无章的数据。所有内容都已经被组织并呈现为一张数据表。此表包含与 CSV 文件相同的标题。因此,如果我们希望数据库中的列具有不同的名称,只需在从 CSV 导入数据之前编辑第 01 行,这样列就会获得新的名称。
然而,只有当你真正理解自己在做什么时,才能这么做,因为一个错误就可能导致数据库完全无用。即使你不喜欢当前的名称,也可以稍后使用 SQL 命令进行更改,因为我们现在处理的不是 CSV 文件,而是数据库。
“这一切都很棒,但我如何访问这个数据库中的信息呢?我本以为它会像 Excel 或其他电子表格程序一样,但我在 MetaEditor 中看到的东西完全没用,对我来说没有任何价值。”
好吧,如果你这么想,那是因为你可能还没有意识到数据库的强大之处,而学会使用数据库需要学习和付出努力。我并无冒犯或打击你的意思。我理解,许多人在看到上图后可能会感到失望,他们原本期待的是更直观、看起来更“像样”的界面效果。从这个角度来看,学习 SQL 似乎毫无意义,或者不值得付出努力。
但让我试着稍微改变一下你的视角。现在,我们终于要来看一个无疑需要付出最多努力去学习的命令。为了使这些概念保持清晰区分,让我们继续讨论一个新的话题。
最后,SELECT 命令
SELECT 命令最简单的语法如下:
SELECT * FROM table;
请注意,这与下方动画中使用的命令完全相同。

但是,我们应该如何解读 SELECT 命令呢?非常简单,不仅仅是这条命令 — SQL 命令经过精心设计,其语法易于理解。为了理解我们刚才所说的内容,让我们来看看如何解读之前展示的命令。
我们应该这样理解:从名为 table 的表中选择所有数据。这是对这条命令的字面解释。如果你真正懂得如何解读它,那么你可能已经意识到,我们可以做一些非常有趣的事情。这只是一个字面解读的示例,但你可以尝试对其他 SQL 命令进行同样的操作。你很快就会发现,学习这些命令的速度会变得相当快,因为每个命令都很容易理解。
回到我们目前关注的内容,让我们来看看动画的结果。在那里,我们得到了相当多的返回记录 — 这正是我们想要的。这是因为,如果我们对只有少量记录的表使用 SELECT 命令,我们可能会认为 SQL 没有意义。然而,当记录数量变得庞大时,学习 SQL 就变得更有价值了。
那么,我们真正面临的问题是什么呢?问题在于返回的数据量。但如果你真正理解了 SELECT 命令的含义,你可能已经在思考如何通过应用某种过滤器来减少数据量了。如果你脑海中闪过这样的念头,那是个非常好的迹象。如果你考虑用其他符号替换星号(*)则更是如此,因为星号是一个通用符号。任何使用过命令行的人都知道这意味着什么。如果你正沿着这样的思路思考,那么你就在正确的轨道上 — 你只需要一点指导来完善你的方法。
现在让我们稍微思考一下:“如果我们替换命令中的星号,为什么还需要这样做才能过滤 SQL 返回的结果呢?”这正是 SQL 语言的设计者在开发该语言时必须回答的问题。请思考片刻并问问自己:当处理大量数据和许多列时,你会如何执行这种筛选?
在解释设计师和开发者如何巧妙地解决这个问题之前,我想再提一下 MetaEditor 中的一个细节。这个细节以后可能会很重要。请看下图。

请注意,我们已将图片的一部分突出显示。原因是,如果您查看突出显示区域的右下角,您会发现已加载了一定数量的记录。在某些情况下,当应用更精细的筛选条件时,您可能需要在这些记录块之间切换,以便查看检索到的数据。点击高亮区域中的箭头,即可跳转到已加载记录的下一个区块。请记住,这些区块是以一千个为一组进行加载的。
因此,高亮区域显示的值代表这些包含一千条记录的块。因此,如果我们想移动到第 8000 个记录的块,只需将值从 1 改为 9,对应于第 8000 个记录的块就会显示在 MetaEditor 中。但为什么是 9?难道不应该是 8 吗?原因是计数是从 1 开始的。但是,值 “1” 代表最多 “1000” 条记录。乍一看,这可能有点令人困惑,但经过一些练习,就会明白其中的道理。
尝试与 MetaEditor 界面交互,以便更好地理解其工作原理 — 在我看来,它比 WorkBench 要简单得多。不过,即使不使用功能更强大的 WorkBench,我们也能做很多事情,尤其是在探索数据库的时候。
好吧,现在让我们回到关于筛选搜索结果的问题。你可能还在思考如何实施一个简单的解决方案。在我看来,SQL 的设计者所创造的解决方案是最佳方案之一。星号也可以替换为其他内容 — 我们下次会讲到。但在过滤方面,开发人员为 SELECT 命令增加了一个新元素。然而,这里有个小窍门:根据我们想要查找的内容以及查找方式的不同,SELECT 命令的语法会有所变化。
首先要理解的是如何在查询中使用列名。这可能看起来有点不寻常。但如果你曾在 Excel 中筛选过结果,你就会知道,你需要先选定一列,然后定义筛选方式 — 根据大于、小于或等于某个特定条件的值进行筛选。同样的道理也适用于 SQL。不同之处在于,我们在这里不是通过点击菜单来操作,而是发送一条 SQL 命令来执行。因此,筛选操作将正确执行。
例如,假设我们希望 SQL 显示 FLAGS 列的值等于 88 的所有记录。那么我们就知道,在 SELECT 命令中,我们需要类似这样的内容:
FLAGS = 88
这似乎很明显,但我们需要在命令中添加一个小细节。所以之前的命令变成了:
SELECT * FROM tb_Quotes WHERE "<FLAGS>" = 88;
请记住,我们的表名为 tb_Quotes。执行此命令时,结果区域将显示 FLAGS 列等于 88 的所有记录。请注意:为什么列名要用引号括起来?因为它被视为字符串。在 SQL 中使用字符串时,必须将其用引号括起来。另外,请注意列名旁边有“大于”和“小于”符号。如果不使用引号,SQL 可能会将这些符号视为其内部语法的一部分。
此时,你可能会想:“为什么要用 SQL 来做这件事?如果我使用 Excel 或类似的程序,我可以更容易地得到相同的结果。我不明白学习SQL的意义何在。”没错,我们刚才演示的内容确实可以在 Excel 中完成 —— 而且更容易。但你忽略了一些东西。目前,我们对 SQL 的工作原理才刚刚开始了解。这些初始任务中的许多确实可以用更简单的工具来完成。
然而,在实际操作数据库时,我们通常会使用相关表和关联查询。这些都是 Excel 和类似工具无法有效处理的事情。这或许可行,但会比使用 SQL 复杂得多、耗时得多、成本也高得多。
还有另一个重要原因导致许多经验丰富的程序员选择不自己实现某些功能 — 他们更喜欢使用 SQL 或类似技术。为了理解讨论的内容,我们需要回到关于 SQL 的第一篇文章。如前所述,使用现有工具通常比从头开始构建一切要好。所以,在这个阶段,当你已经知道如何在数据库中创建、插入、更新、删除和查看记录时,我们可以更深入地探讨一下那篇文章中讨论的内容。
回想一下我们迄今为止所讲的内容。若使用 Python 等编程语言来实现相同的结果,则需要花费更多的时间来创建、测试和开发必要的逻辑。这是因为你不用 SQL,而是选择用 Python 来做同样的事情。我不是说你做不到。我只是想说,要实现我们目前所看到的这些功能,你需要更多的时间来创建、测试和开发子程序。
请记住:我们只介绍了 SQL 的基础知识。即便是具备深厚 Python 知识的熟练程序员,也需要数天甚至数周的时间才能构建出与 SQL 已能高效完成的任务相当的功能。我们会再次讨论这个话题,因为我不想让你浪费时间去做无谓的重复工作。即使只学习 SQL 的基础知识 — 尤其是如何正确使用它 — 你也会明白,重新创建 SQL 已经提供的功能是毫无意义的。
最后的想法
到目前为止,我们还没有展示 SQL 的一个关键方面。尽管我们在之前的文章中有所提及,但我们尚未深入探讨数据库为何会成为一个如此庞大的主题。既然我们已经介绍了用于搜索信息的基本命令,接下来我们可以更深入地探讨那些使 SQL 成为强大专业人士必备技能的概念。在下一篇文章中,我们将对 SQL 编程进行更多讨论,因为还有一个概念需要学习和解释。
这一概念包括主键和外键,在创建相关表系统时,这一点非常重要。使用关联表的能力极其重要,这主要是因为它们在搜索数据库时非常有用,而且它们还使我们能够执行和创建一些原本不可能完成的任务。所以,如果你真的对数据库这个话题感兴趣,千万不要错过下一篇文章,因为内容会变得更加严谨。
| 文件 | 描述 |
|---|---|
| Experts\Expert Advisor.mq5 | 演示 Chart Trade 与 EA 之间的交互(交互需要 Mouse Study)。 |
| Indicators\Chart Trade.mq5 | 创建一个窗口,用于配置要发送的订单(需要 Mouse Study 才能进行交互) |
| Indicators\Market Replay.mq5 | 创建用于与回放/模拟服务交互的控件(交互需要 Mouse Study)。 |
| Indicators\Mouse Study.mq5 | 提供图形控件与用户之间的交互(回放系统和真实市场交易都需要)。 |
| Services\Market Replay.mq5 | 创建并维护市场回放/模拟服务(整个系统的主文件)。 |
| Code VS C++\Servidor.cpp | 创建并维护一个用 C++ 开发的套接字服务器(迷你聊天版本)。 |
| Code in Python\Server.py | 创建并维护用于 MetaTrader 5 和 Excel 之间通信的 Python 套接字。 |
| Indicators\Mini Chat.mq5 | 通过指标实现迷你聊天(需要服务器运行)。 |
| Experts\Mini Chat.mq5 | 通过 EA交易实现迷你聊天(需要服务器运行)。 |
| Scripts\SQLite.mq5 | 演示如何在 MQL5 中使用 SQL 脚本。 |
| Files\Script 01.sql | 演示如何创建带有外键的简单表。 |
| Files\Script 02.sql | 演示向表中插入数据。 |
本文由MetaQuotes Ltd译自葡萄牙语
原文地址: https://www.mql5.com/pt/articles/12928
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
新手在交易中的10个基本错误