C#/.NET量化开发实现财富自由【5】搭建属于你自己的A谷数据库

量化开发期间,每次都获取券商数据,总是一个麻烦事。所以搭建一个本地的数据库进行存储,可以节约很多不必要的性能和资源开销。一般情况下,建议使用clickhouse数据库来当做你的数据库存储。不过本文章为了快速入门,就以postgresql为例来做数据库存储。

本地postgresql我使用的debian系统进行安装。使用debian的原因:debian的shell操作可以兼容更多的Linux系列操作系统,例如Ubuntu系列、华为欧拉系列、麒麟操作系统系列等。

步骤 1: 更新系统

首先,确保你的系统是最新的。打开终端并执行:

sudo apt update
sudo apt upgrade

67ab8657f04b9ea2183b28dee6f503cd.png

步骤 2: 安装PostgreSQL

Debian的官方仓库中包含了PostgreSQL。你可以直接安装最新的PostgreSQL版本。运行以下命令来安装:

sudo apt install postgresql

8e2c505078769d4b66b9c8ee44a5e139.png

步骤 3: 启动和启用服务

安装完成后,PostgreSQL服务通常会自动启动。你可以检查服务状态:

sudo systemctl status postgresql

cb7e8a7afaf5eebba55f018d7427bcd0.png

如果服务没有运行,你可以启动并设置开机启动:

sudo systemctl start postgresql
sudo systemctl enable postgresql

f6e91d18240b3eaa5caab71db03cda62.png

步骤 4: 创建数据库和用户

安装完毕后,你可以开始创建数据库和用户。首先,切换到postgres用户:

sudo -i -u postgres

cc574c777b7806fa628bb1f817cb4f22.png

然后,你可以进入PostgreSQL命令行界面:

psql

6669a8e4c90d4ae1d571d90e057e404a.png

在这里,你可以创建一个新的用户和数据库,并授予用户权限:

CREATE USER myuser WITH ENCRYPTED PASSWORD 'mypassword';
CREATE DATABASE mydb;
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;

7aa5862329bb2e4c7c2ebcef54895228.png

授予public的权限

-- 给予特定用户对schema 的使用权限

GRANT USAGE ON SCHEMA my_schema TO your_user;

-- 给予特定用户对 schema 中所有表的所有权限

GRANT ALL ON ALL TABLES IN SCHEMA my_schema TO your_user;

-- 设置默认权限,以确保将来在 schema 中创建的所有新表都将自动给予特定用户相应权限

ALTER DEFAULT PRIVILEGES IN SCHEMA my_schema GRANT ALL ON TABLES TO your_user;

d2bea22e7fb408cc5f5bd01226ba43e6.png

4c22455241ccd752955b5551e592f226.png

退出psql使用\q,然后回到普通用户使用exit。

步骤 5: 配置远程访问

如果你需要远程连接到你的PostgreSQL数据库,你需要修改postgresql.conf和pg_hba.conf文件。这些文件通常位于/etc/postgresql/版本/main/目录中。

【备注】我当前最新版本是15版本,如果以后你们下载的可能不是15版本,请根据实际版本进行配置。例如配置默认路径里面的15是实际你自己的版本,例如16、17、18等等。

编辑postgresql.conf,设置listen_addresses为'*':

sudo vim /etc/postgresql/15/main/postgresql.conf

在文件中找到listen_addresses并修改它:

listen_addresses = '*'

改变前:

4267aaf25df9119cebb4c70a9cb080c3.png

改变后:

633a4fad25518f0944eb2f099426b4f3.png

编辑pg_hba.conf,添加或修改规则以允许远程连接:

sudo vim /etc/postgresql/15/main/pg_hba.conf

在合适的位置添加:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

host    all             all             0.0.0.0/0               md5

8124aaec4280a442d1e72d1101e7b24f.png

重启PostgreSQL服务使更改生效:

sudo systemctl restart postgresql

810aae491d97008a0c57d0c3f292f89f.png

然后可以使用一些客户端工具来连接数据库,例如DataGrip、Navicat、Dbeaver等等都可以。

c096217005fa2d7f8a65e1416a9bf04e.png

并且里面没有任何表结构等信息。

d29bcb45c84de365e233d260cabfb6c2.png

实现根据表名称自动创建指定的表结构。用于存放所有大A的历史数据。先创建一个实体类,并用来指定表字段名称,用于统一生成所有股票的表结构。

e8562b70a6cd926a1dbde182c689c772.png

以及预留三个字段,存储DIF、DEA、MACD数据

9f348ee3dad62fec3c56738ab761ef9f.png

创建一个简单的帮助类,用于操作数据库使用。并且实例创建以后,默认提供一个获取sqlsugarscope对象的方法,以及获取已有表信息的集合。

1608e6c6e37468a027447655a68403d3.png

最后提供一个创建表结构的方法,用于指定表结构所需要的实体类,以及表名称。表名称此处可以以股票代码为表名称

772319bedaa2615dcfedd185f2d83500.png

对之前获取股票清单的地方,做一个创建表的操作。此处为了简单操作,大佬们可以对帮助类做其他拓展,以便于支持依赖注入等。

c0ab8d310667354a07880ae5e3b30977.png

开始执行,可以看到表结构在持续性创建

f6eca7f4270b31a46aeaf019abb58d8b.png

展开任意一个表,可以看到字段都被成功创建了。后续这些表就会被用于存储对应表名称的股票代码的所有历史数据。

df0731f703768ab79d6ed3027751fb30.png

执行完毕以后,可以看到总共5361个表。

59e76e5d3f42e3dc2be894bf635ae990.png

接下来,在数据库操作帮助类里面,新增CRUD有关操作

79dc1204c8060212403aa0432a9a4f94.png

对获取历史数据的操作,做个改造,获取历史数据以后也计算DIF、DEA、MACD数据,并一起写入数据库:

d0f70f6351cf4be7bc001c311029c0db.png

执行获取历史任务job,可以看到刷刷刷的获取记录信息。

8c25f2d941fd872167cc42997e26c50d.png

打开数据库表,查看数据,可以看见数据写入成功,并且dif、dea、macd数据也都记录成功。和通达信等app上面的数据也一致(app显示的是四舍五入以后的数据)

b2edcb01e2da5a76fcbd7fa440b0f5ae.png

等待程序执行完毕,整个历史数据就生成成功了。历史数据可以用来方便计算你的策略的历史模拟战绩,形成你的个人财富。

以上只是抛砖引玉,大家还可以自行保存分钟数据、周数据、每个交易日收盘以后自动新增当天数据等进行维护,此处就不一一列举了。

数据库核心操作帮助类,供参考:

public class DatabaseHelper
{
    private DbTableInfo[] _initTables=new DbTableInfo[0];
    private SqlSugarScope _sqlScope = null;


    public DatabaseHelper()
    {
        _sqlScope = GetDbScope();
        GetTableList(_sqlScope);
    }


    /// <summary>
    /// 返回表名称
    /// </summary>
    /// <returns></returns>
    public string[] GetStockTableNames()
    {
        return _initTables.Select(x => x.Name).ToArray();
    }




    private SqlSugarScope GetDbScope()
    {
        var db = new SqlSugarScope(new ConnectionConfig()
        {
            ConnectionString = "Host=ip;Port=port;Username=username;Password=pwd;Database=dbname;",
            DbType = DbType.PostgreSQL,
            IsAutoCloseConnection = true,
            InitKeyType = InitKeyType.Attribute
        });
        return db;
    }


    /// <summary>
    /// 获取已有的数据库表
    /// </summary>
    /// <param name="db"></param>
    /// <param name="tableName"></param>
    /// <returns></returns>
    private void GetTableList(SqlSugarScope db)
    {
        _initTables = db.DbMaintenance.GetTableInfoList(false).ToArray();
    }


    public void CreateTableWithCustomName<T>(string tableName)
    {
        try
        {
            if (!_initTables.Any(x => x.Name == tableName))
            {


                _sqlScope.MappingTables.Add(typeof(T).Name, tableName);
                // 通过动态指定表名来初始化或迁移表结构
                _sqlScope.CodeFirst.InitTables<T>();


                // 解除映射
                _sqlScope.MappingTables.Remove(new MappingTable() { EntityName = typeof(T).Name });


            }
            else
            {
                Debug.WriteLine($"Table '{tableName}' already exists.");
            }
        }catch(Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }


    /// <summary>
    /// 映射表
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tableName"></param>
    private void UseTable<T>(string tableName)
    {
        _sqlScope.MappingTables.Add(typeof(T).Name, tableName);
    }


    /// <summary>
    /// 插入数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tableName"></param>
    /// <param name="data"></param>
    public void InsertData<T>(string tableName, List<T> data) where T : class, new()
    {
        UseTable<T>(tableName);
        _sqlScope.Insertable(data).ExecuteCommand();
        _sqlScope.MappingTables.Clear(); // 清理映射以防止后续操作错误
    }


    /// <summary>
    /// 查询
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tableName"></param>
    /// <returns></returns>
    public List<T> QueryData<T>(string tableName) where T : class, new()
    {
        UseTable<T>(tableName);
        var result = _sqlScope.Queryable<T>().ToList();
        _sqlScope.MappingTables.Clear();
        return result;
    }


    /// <summary>
    /// 更新
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tableName"></param>
    /// <param name="data"></param>
    public void UpdateData<T>(string tableName, List<T> data) where T : class, new()
    {
        UseTable<T>(tableName);
        _sqlScope.Updateable(data).ExecuteCommand();
        _sqlScope.MappingTables.Clear();
    }


    /// <summary>
    /// 删除数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="tableName"></param>
    /// <param name="data"></param>
    public void DeleteData<T>(string tableName,List<T> data) where T : class, new()
    {
        UseTable<T>(tableName);
        _sqlScope.Deleteable(data).ExecuteCommand();
        _sqlScope.MappingTables.Clear();
    }


    /// <summary>
    /// 删除指定的表
    /// </summary>
    /// <param name="tableName"></param>
    public void DropTableIfExists(string tableName)
    {
        if (_sqlScope.DbMaintenance.IsAnyTable(tableName, false))
        {
            _sqlScope.DbMaintenance.DropTable(tableName);
        }
        else
        {
            Debug.WriteLine($"Table {tableName} does not exist.");
        }
    }


}

谷市有风险,量化需谨慎~大佬们且量且珍惜~

dcf3560b4f7ed0d78ac3b554b609b1eb.png

如果觉得有帮助,欢迎点赞+转发+收藏+关注【Dotnet Dancer】~谢谢大佬们,祝大佬们早日财富自由~

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值