首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
158 阅读
2
nvim番外之将配置的插件管理器更新为lazy
107 阅读
3
2018总结与2019规划
76 阅读
4
从零开始配置 vim(15)——状态栏配置
74 阅读
5
PDF标准详解(五)——图形状态
51 阅读
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
linux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
Thinking
FIRE
菜谱
登录
Search
标签搜索
c++
c
学习笔记
windows
文本操作术
编辑器
NeoVim
Vim
win32
VimScript
emacs
linux
elisp
读书笔记
文本编辑器
Java
反汇编
OLEDB
数据库编程
数据结构
Masimaro
累计撰写
337
篇文章
累计收到
32
条评论
首页
栏目
软件与环境配置
博客搭建
从0开始配置vim
Vim 从嫌弃到依赖
linux
Emacs
MySQL
Git与Github
AndroidStudio
cmake
读书笔记
编程
PDF 标准
从0自制解释器
qt
C/C++语言
Windows 编程
Python
Java
算法与数据结构
PE结构
Thinking
FIRE
菜谱
页面
归档
友情链接
关于
搜索到
337
篇与
的结果
2025-09-18
Emacs 折腾日记(三十)——打造C++ IDE 续
上一篇博客中,我完成了C++ IDE初步工作,包括代码的高亮、折叠、跳转以及补全等工作。但是作为IDE来说功能还有点不够,就我个人而言作为IDE来说它还需要具备一键编译运行和调试功能。这篇文章就来记录我是如何实现上述功能的编译运行我使用的演示项目比较简单,它的文件结构如下:. ├── include │ └── head.h └── src ├── add.cpp ├── div.cpp ├── main.cpp ├── mult.cpp └── sub.cpp它分为两个目录分别保存头文件和源文件。其中头文件只有一个定义各个接口函数,而接口函数的实现就放到各自定义的cpp文件中。这里使用加减乘除的四则运算的实现来作为演示。这里我分别演示一下Make文件和CMake构建的项目是如何实现一键编译运行的。Make构建的项目针对上前面介绍的简单项目,我们可以写出如下的Makefile# 编译器设置 # 定义项目根目录 ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) CXX := g++ CXXFLAGS := -Iinclude -Wall -Wextra -pedantic -std=c++11 -MMD -MP LDFLAGS := EXE_OUTPUT := $(ROOT_DIR)bin TARGET := $(EXE_OUTPUT)/app $(info TARGET = $(TARGET)) # 源文件和对象文件设置 SRC_DIR := src SRCS := $(wildcard $(SRC_DIR)/*.cpp) OBJ_DIR := $(ROOT_DIR)build/obj OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRCS)) DEPS := $(OBJS:.o=.d) # 默认目标(第一个目标) all: $(TARGET) # 链接生成可执行文件 $(TARGET): $(OBJS) @mkdir -p $(@D) $(CXX) $(LDFLAGS) $^ -o $@ # 编译源文件并生成依赖 $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR) $(CXX) $(CXXFLAGS) -c $< -o $@ # 创建对象文件目录 $(OBJ_DIR): mkdir -p $@ # 包含自动生成的依赖关系 -include $(DEPS) # 清理生成的文件 clean: rm -rf $(TARGET) build .PHONY: all clean 上面我们定义了头文件路径为include 目录,并且规定了中间文件生成在 build/obj 中,最后定义了生成可执行程序在 bin/app 中对于编译来说,Emacs内置了 compile 命令,它会自动执行 make -k 命令,但是如果我在使用Emacs的过程中切换到了其他目录的话,还需要特别指定Makefile 所在的路径,对我来说我希望能在尽可能少输入参数的情况下完成同样的操作,不太希望每次都指定项目根目录,好在之前配置的projectile 插件帮助我们识别出来了项目的根目录。所以这里可以使用 projectile-compile-project 来自动指定根目录并编译。从上面的截图可以看到,flycheck 提示了几个错误,这是因为项目没有生成 compile_commands.json文件,所以lsp服务器无法跨文件分析,导致找不到头文件。原始的make 命令并不支持生成 compile_commands.json 文件,我们可以通过 bear 命令来完成这个工作,它的用法比较简单,只需要使用 bear -- <your-build-command> 即可, 对于使用make编译的项目来说 <your-build-command> 代表的就是 make 命令。我们需要考虑的一个问题是,如何将bear加入到编译命令中,也就是将它自动生成的 make -k 给替换掉,第二个问题是如果当前目录在其他目录下,如何保证 compile_commands.json 永远生成在根目录下Emacs中有一个变量 compile-command 保存了编译的命令,如果我们使用Emacs自带的compile来编译可以通过修改它来实现,而 projectile-compile-project 则是通过变量 projectile-project-compilation-cmd 来保存编译命令,默认是nil,对于使用 projectile 我们通过修改这个变量的值从而修改编译时使用的命令。另外既然 projectile 可以得到项目的根目录,我们就可以利用这个插件来获取项目的根目录,有了这些信息通过一个函数就可以重新生成一个编译命令(defun my/general-compile-command() (concat "bear --output " projectile-project-root "compile_commands.json" " -- make -k"))这个函数的代码非常简单,通过 projectile-project-root 来获取项目的根目录,然后通过字符串拼接的方式来得到编译命令生成 compile_commands.json 成功之后,我们重启 lsp 服务后可以看到错误都消失了,只有两个警告了了解了编译的一些情况,下面来看看如何在Emacs中执行生成的可执行程序。Emacs中可以使用 shell-command 来执行可执行 shell 命令。例如我们可以在项目的根目录下执行 shell-command ./bin/app。很明显如果每次都指定程序的路径是非常麻烦的事,我希望能有一个命令或者函数来自动执行可执行程序。但是Makefile构建的项目比较古老也灵活,Makefile中没有一个固定的方式或者写法来指定可执行程序的生成路径,也就是说没有一个通用的方式来根据Makefile获取可执行文件的路径。一种折中的方案就是针对每个项目都定义一个 execuable-path 的变量来指定可执行程序的路径,然后再通过elisp代码来根据这个变量执行程序(defun my/run-program() (interactive) (shell-command (concat projectile-project-root executable-path)))我们可以针对每个项目单独设置一个 executable-path 变量。Emacs会读取项目根目录中的 .dir-locals.el 文件,并且将文件中定义的变量作为项目的局部变量,所以我们只需要在该文件中定义好 executable-path 就可以了。我们可以通过命令 add-dir-local-variable 来往该文件中添加一个局部变量,也可以自己手写该文件实现这一操作添加完变量之后,项目根目录中的 .dir-locals.el 文件内容如下;;; Directory Local Variables -*- no-byte-compile: t -*- ;;; For more information see (info "(emacs) Directory Variables") ((c++-mode . ((executable-path . "bin/app"))))在重启Emacs之后,执行这个函数就可以做到一键运行了有了这些,我希望能将它们有机的组合起来,也就是说按下某个快捷键,这里我暂时定义为 <F7>。它直接同时执行编译和运行的操作。通过 C-<F7> 来完成重编译的操作。;; 重新编译 (defun my/rebuild-program () (interactive) (let ((root (file-name-as-directory (projectile-project-root)))) (shell-command (concat "make clean -C " root)) (setq compile-command (concat "bear --output " root "compile_commands.json" " -- make -k -C " root)) (compile compile-command))) ;; 绑定快捷键 (setq compilation-read-command nil) ;; 取消编译时确定命令行 (evil-define-key 'normal c++-mode-map (kbd "<f7>") #'projectile-compile-project) (evil-define-key 'normal c++-mode-map (kbd "C-<f7>") #'my/rebuild-program))) 这里的代码比较简单,对于编译来说只需要将之前执行的 projectile-compile-project 绑定到对应的快捷键;对于重编译,我通过函数 my/rebuild-program 来完成。这个函数主要操作是先执行 make clean 命令然后重新执行 make。在正式绑定快捷键之前,有一句 (setq compilation-read-command nil) 。projectile-compile-project 和 compile 命令都是交互式命令,执行时会首先显示对应的编译命令,需要用户手动执行回车确认命令,这句代码的意思是不取消它们需要确认的步骤,直接执行命令。本来我打算在重编译函数中也采用 projectile-compile-project 但是它这个交互式我一直取消不了,所以这里我直接采用 compile 指定根目录的方式来完成这个操作。如果想要绑定一键运行的操作也可以采用这个思路,将快捷键绑定到 my/run-program 函数中,这个函数也可以添加一个编译命令确保执行的是最新代码生成的可执行程序CMake工程CMakeLists.txt 文件内容如下:cmake_minimum_required(VERSION 3.15) set(CMAKE_CXX_STANDARD 11) project(test) # aux_source_directory(${PROJECT_SOURCE_DIR} source) file(GLOB source ${CMAKE_SOURCE_DIR}/src/*.cpp) include_directories(${CMAKE_SOURCE_DIR}/include) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) add_executable(app ${source})这个CMakeLists.txt 文件中主要定义了编译使用到的源文件、头文件目录路径和生成的exe路径emacs 中有一个名为 cmake-ide 的包,它用于读取cmake配置中的各项参数并将参数传递到对应的包中,虽然用它可以很方便的针对cmake配置,但是它依赖rtags,并且没有支持lsp-mode。所以这里就淘汰它,还是想办法自己实现针对cmake来说,要生成 compile_commands.json 比较简单,我们可以在命令行中使用cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1也可以在cmake配置文件中,project命令之后添加set (CMAKE_EXPORT_COMPILE_COMMANDS ON)这里我采用将命令写到cmake文件中的方式。对于cmake 编译的过程主要由两个部分组成,首先是cmake构建项目生成Makefile,然后使用make 命令编译项目。我们要实现自动编译也需要模拟这两个命令。与上面类似,这里我只需要将 my/general-compile-command 函数做少许改动即可(defun my/cmake-general-compile-command () (concat "cmake -B " (projectile-project-root) "build -DCMAKE_BUILD_TYPE=Debug " (projectile-project-root) " && ln -sf " (projectile-project-root) "build/compile_commands.json " (projectile-project-root) "compile_commands.json" " && cmake --build " (projectile-project-root) "build --config Debug"))这个函数生成的命令主要完成三个工作,将构建编译生成的临时文件放到 build 目录下;因为生成的 compile_commands.json 文件也一起放在了 build 目录中,所以我加一个软链接到项目根目录的操作;最后就是执行编译操作了。至于重编译则于上面的步骤相似,cmake一般我习惯删除存放临时文件的build目录然后重新执行cmake构建。所以这里还是模拟这个过程(defun my/cmake-rebuild-program () (interactive) (let ((root (file-name-as-directory (projectile-project-root)))) (shell-command (concat "rm -rf " root "build")) (setq compile-command (my/cmake-general-compile-command)) (compile compile-command)))至于运行程序,我们还是可以采用上面介绍的指定程序生成路径的方式。也就是不管使用cmake或者Makefile 构建的工程都可以使用上面定义的 my/run-program 函数来运行程序调试作为IDE的一个重要或者说基础的功能,调试功能是必不可少的。emacs 自身支持使用gdb进行调试,我们可以执行 M-x gdb 来启动一个调试示例,这个时候我们一边通过gdb的调试命令来控制程序语句的执行一边观看代码的上下文。但是目前流行的方式是使用 dap 来调试程序,至于什么是dap,我在配置vim的时候已经介绍过了,这里就不再赘述了emacs 中有一个名为dap-mode 的插件通过这个插件可以实现dap相关的功能。因为在介绍vim配置的时候我使用的是vscode中的 cpptools插件,这里我打算也使用它来作为dap的调试后端,可以通过cpptools官方仓库 进行下载接着需要安装lldb-vscode,它是针对vscode的一个插件,我们可以在 官方仓库 中找到对应的下载包。下载完成之后可以直接解压到对应目录,这里我解压到 ~/.emacs.d/cpptools 目录中。此时对应的调试后端程序为 ~/.emacs.d/cpptools/extension/debugAdapters/bin/OpenDebugAD7。我们需要赋予它可执行的权限。在这些工作都做好之后,可以使用下面的代码来安装dap-mode(use-package dap-mode :ensure t :after (lsp-mode) :config (dap-auto-configure-mode) ; 可选:启用自动配置 (setq dap-cpptools-debug-program '("~/.emacs.d/cpptools/extension/debugAdapters/bin/OpenDebugAD7")) )我们可以通过命令 dap-debug-edit-template 创建一个调试的模板。对给出的模板做一些简单的修改(dap-register-debug-template "cpptools::Run Configuration" (list :type "cppdbg" :request "launch" :name "cpptools::Run Configuration" :MIMode "gdb" :program "${workspaceFolder}/bin/hello" :cwd "${workspaceFolder}" :environment [] :miDebuggerPath "/usr/bin/gdb")) 我们执行一下这个代码就会向Emacs注册一个调试的模板。接着直接调用 dap-debug 即可启动调试。虽然我们可以将上述注册的代码放到主配置文件中,但是其中的一些关键的字段,例如程序的位置,使用的环境变量,以及对应的调试参数都无法做到所有程序都统一,所以这里我觉得还是需要的时候直接修改就好了。dap-mode 的一些命令如下:dap-debug 和 dap-continue : 启动调试或者运行到下一个断点处dap-next : 执行下一句代码dap-step-in : 执行下一行代码并进入函数内部dap-step-out : 执行到函数返回dap-breakpoint-toggle : 创建或者删除端点我们可以对这些命令进行键位绑定(use-package dap-mode :ensure t :after (lsp-mode) :config (dap-auto-configure-mode) ; 可选:启用自动配置 (require 'dap-cpptools) (setq dap-cpptools-debug-program '("~/.emacs.d/cpptools/extension/debugAdapters/bin/OpenDebugAD7")) (evil-define-key 'normal dap-mode-map (kbd "<f10>") #'dap-next) (evil-define-key 'normal dap-mode-map (kbd "<f9>") #'dap-breakpoint-toggle) (evil-define-key 'normal dap-mode-map (kbd "<f5>") #'dap-debug) )这样我们可以使用上述快捷键来进行调试操作总结这篇文章花了好长时间才弄出来,主要是我对于emacs和lisp语言不太熟悉,中间在尝试编写一键运行和配置dap时耗费了大量的时候。最终我还是成功了,至少我完成我当初想要的一些ide的基本功能,当然在使用上还是比不过vscode,但是在折腾中总能找到一丝乐趣。本文中的配置仅仅经过我自己机器的检验,本来想弄的更加灵活更加接近vscode的体验,有一些我自己想要的功能还没加上,仅仅做了一个可用的玩具。但是我没有想到什么办法,而且这篇文章已经憋了好久了,再不写点东西出来我感觉马上就要放弃了,我想先弄点东西出来给自己一个激励,让我有动力继续深入学习一下Emacs的其他内容。等我多学了一点Emacs多写了一点elisp代码之后可能会对调试和编译方面的代码做一个大的更新。最后如果有读者觉得这篇文章写的有那么一点帮助,那将是我的荣幸,感谢读者在百忙之中能读完本文。
2025年09月18日
6 阅读
0 评论
0 点赞
2025-09-03
Ubuntu 20.04 安装gcc5.4 与 cmake3.16 编译环境
因为公司的编译环境使用的是Ubuntu 20.04 搭配 gcc5.4 和 cmake3.16。所以我也在自己的开发机上安装了配套的环境Ubuntu 就使用 WSL2 直接安装就行,编译环境因为Ubuntu 20.04 默认使用的是gcc 9的版本,所以配置起来还是需要稍微费点功夫的。这里记录一下有效的步骤防止后续又需要配置这套环境的时候满世界找因为gcc5.4 相对来说比较老了,这一版Ubuntu 的官方软件源仓库中没有,需要添加额外的软件源仓库我们可以选择先备份原始的软件源,然后将下列源添加到 /etc/apt/sources.list 文件的末尾deb http://archive.ubuntu.com/ubuntu xenial main universe然后执行sudo apt update && sudo apt upgrade更新软件源接着安装gcc 5.4 以及对应的32位环境支持sudo apt install -y gcc-5 g++-5 gcc-5-multilib g++-5-multilib sudo apt install -y libc6-dev-i386 lib32stdc++6 lib32gcc1默认情况下,ubuntu 20.04 中安装的gcc版本是9.0,如果我们自行安装了 gcc5.4,系统中会有多个gcc版本有时候会导致冲突,我们可以使用下面的命令来管理多个gcc版本# 配置备选版本 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 50 # 切换版本(选 5.4 对应的编号) sudo update-alternatives --config gcc sudo update-alternatives --config g++此时使用 gcc --version 将会看到当前gcc的版本是5.4Ubuntu 20.04 官方的软件源中cmake的版本就是 3.16,所以对于cmake直接使用sudo apt install cmake
2025年09月03日
7 阅读
0 评论
0 点赞
2025-08-31
读 《动物农场》
故事发生在一个月黑风高的晚上,农场中德高望重的老猪“上校”在即将因为衰老而死去之前召集了农场中的众多动物,决定将它所获得的智慧传授给这些其他动物。农场中的动物劳作一生,却仅仅只能勉强活下去,温饱自然不能奢求,它们的一生只有受苦受难受奴役。但是这些并不是因为农场地穷土薄。这一切都是因为人类偷走了动物的劳动果实,人类不进行生产活动却获得了动物们辛勤劳作的产出。只有打倒人类,劳动成功就是自己的了,几乎在一夜之前就能变得富足、自由。“上校”也强调在赶走人类之后切不可落到去效仿人类,即使征服了人类,也不可将它们的恶习继承下来。最后动物们歌唱了《英格兰的生灵》“上校”在三天后就去世了,但是革命的种子在此就种下了了。教育和组织动物的职责落到了被认为动物中最聪明的猪身上,它们分别是雪球和拿破仑以及一只叫做吱嘎的小肥猪。吱嘎的最大本事就是将白的说成黑的。在动物中宣传革命理论也不是那么容易的,有些动物还是认为它们有义务支持农场主琼斯先生,并且认为“我们是琼斯先生养活的,要是他死了,我们就得饿死”。有一次琼斯忘记给动物喂食导致母牛擅自将饲料棚打开。动物们自行从料箱取食,这激怒了琼斯,在琼斯对着动物们拳打脚踢并且拿鞭子抽打动物的时候,动物们实在是忍无可忍,最终动物们决定反抗。在冲突中动物们最终取得胜利,并且将琼斯赶出了农场。在革命成功后,动物们将曾今琼斯用来奴役动物的马嚼子、鼻环、狗链、缰绳、眼罩等工具付之一炬。并且封锁了琼斯的房间,里面的酒、床等被视作堕落腐化的象征并且禁止任何动物进入。曾今领导革命的猪头头们将动物主义的原理精简为《七戒》写到大谷仓的外墙上:凡是用两条腿行走的都是敌人凡是用四条腿行走的或者长翅膀的都是朋友凡是动物不可穿衣服凡是动物不可睡床铺凡是动物不可饮酒凡是动物不可杀戮别的动物凡是动物一律平等最终这个庄园被命名为动物农场、由鸽子向外其他农场输出革命理论。在农场中诞生了九只小狗崽,拿破仑将它们从母亲身边带走,说是要对它们的教育负责,它将小狗崽放到阁楼中,并且对外仅仅隐蔽。在农场中发生了牛奶和苹果丢失的事件,不久之后发出了公告,牛奶和苹果被拌入猪食。别的动物对此颇有微词。但是吱嘎解释道“并不是猪们贪图享受,只是农场的组织部门需要猪们动用大脑,是脑力劳动,吃苹果喝牛奶只是为了补充脑力,更好的为动物们的福祉进行工作,更好的为了动物谋福利”。并且吱嘎还威胁到如果猪不能恪尽厥责,琼斯将会回来。动物对此就不再有异议了。雪球在日以继夜的研究做一种风车,有了风车动物们就可以有电力,有热水澡可以洗,并且也可以使用电力来转动磨盘减轻动物的劳动负担。在雪球向动物们发表它的政见鼓励动物们赞成建造风车时,拿破仑公开反对制造风车并且发动了政变。它利用之前收养教育的九条长大的小狗崽将雪球驱逐出动物农场。拿破仑掌权后,取消了每周日的民主碰头会,接着成立了一个专门的委员会来决定农场运作的所有事务,成员全都由猪担任,它自己担任委员会的主席。动物们在星期日上午聚在一起向农场的场旗致敬,唱《英格兰的生灵》,接受下达给它们的一周工作任务。但是不再有之前的民主讨论。雪球被驱逐的事虽然在动物圈中引起了一定的讨论但是吱嘎向动物们解释称雪球与琼斯勾结,最终还是以一句“同志们,你们也不希望琼斯回来吧”打消了动物们的疑虑。在雪球被驱逐的三周以后拿破仑决定要建造风车,对此吱嘎向动物们解释这是拿破仑的策略,表面上反对实际是一种迂回战术。在拿破仑当权的那一年动物们自始至终像奴隶一样干活,但是它们清楚的意识到它们干活主要是为了自己,而不是为了不劳而获,转世盗窃的人类。它们每周要工作60小时,这种劳动遵循自愿原则,但是按照多劳多得的原则,不参加加班的动物需要减去一半口粮。动物委员会宣布,它们将会与人类进行交易,动物们虽然有意见,但是在吱嘎的忽悠下也打消了疑虑。动物们在农场上看到拿破仑四肢着地却对着两脚站立的人类下达命令,一股自豪感在它们心中油然而生。在此之后猪们打开了之前封锁的琼斯的阁楼,并且住了进去。动物们虽有疑虑但是吱嘎说,作为动物农场的首脑部门需要一个安静的工作环境,住楼房比住猪圈更能体现伟大领袖的尊贵身份。并且猪们堂而皇之的谁在了人类的床上。动物们明明记得当初的《七戒》规定了凡是动物不可睡床铺。但是吱嘎却说“床的意思仅仅是睡觉的地方而已,戒律针对的是被单,我们已经把被单从农场主宅内的床上撤去,睡在上下两条毯子中间”。并且吱嘎说舒服的睡眠是为了更好的为动物服务,阻止琼斯将来回来。拿破仑为了与人类进行贸易宣布要从母鸡那里拿鸡蛋,并且规定母鸡每天需要产一定数量的鸡蛋,在母鸡进行反抗之后拿破仑宣布停止给母鸡饲料并且也禁止任何动物给母鸡哪怕一颗玉米粒,最终在有9只母鸡死亡的情况下终于停止了反抗。最终死亡的母鸡被埋葬,最终拿破仑宣布母鸡死于疾病。在这个时期风车建造失败了,但是拿破仑将这一切归咎于逃走的雪球并且将农场中发生的一系列不好的事都归咎于雪球,就这样雪球莫名其妙的背负了诸如偷吃谷物、打破鸡蛋、践踏苗床等等罪过,就像它的名字那样,它的罪过也像滚雪球一样越滚越大。哪怕它在反抗琼斯的斗争中身先士卒并且也为之负伤,这也被描述成它事先与琼斯勾结故意演戏。甚至在之后的批判中被认为是雪球一伙的几个动物被处决,墙上的《七戒》中“凡是动物不可杀戮别的动物”这一条也被修改为“凡动物不可杀戮别的动物,如果没有什么理由的话”。动物们付出了比过去更加辛苦的劳动但是仍然食不果腹,仍然生活在饥寒之中。每周日吱嘎总是会工具一串串的数字,从数字上来看各档粮食产量一直在增加,但是它们就是吃不饱。动物们宁愿少听点数字,多得到点吃的。在一段时间之后,其他动物也不能随便直呼拿破仑的名号,在任何时候需要称它为“我们的领袖拿破仑同志”。猪们同时也为它冠以“动物之父”、“人见愁”、“羊圈守护神”、“小鸭之友”的头衔。农场无论取得什么成绩都要归功于拿破仑英明的领导。《七戒》中“凡是动物一律平等”也被修改为“凡是动物一律平等,但是有的动物比其他动物更平等”。慢慢的《七戒》中“凡是动物不可饮酒”被修改为“凡是动物不可饮酒过量”。拿破仑与猪们也开始饮酒,并且将原来准备给动物们安度晚年的一块水果园改种大麦。后面经历过几次人类的反扑,动物中最任劳任怨,力气最大的马——拳击手在一次反抗人类侵略的战争种受伤了,但是它仍然为了建立风车辛苦劳作,终于在某一天它再也起不来了。拿破仑在得知此事之后吱嘎现身了,它对拳击手带来了来自拿破仑的慰问,同时代表拿破仑对拳击手表示了同情和关怀,他承诺会将拳击手送到医院接受治疗。但是在医院的车准备将拳击手拉走之时,它的好友驴子本杰明却发了疯的组织车子的离开,本杰明在后面狂追医院的车。动物们都十分惊讶本杰明的样子,它过去的形象是沉稳中带有点不谙世事,它似乎从来没有将什么事放在心上。在追车失败之后怒喝道“笨蛋,都是笨蛋!难道你们每瞧见车身上写的什么字?”在动物们惊诧的眼神中,本杰明公布了真相,这辆车并不是医院的车,而是屠马场的车。吱嘎回来之后虚构了拳击手在医院的场景,宣布拳击手在医院不治身亡的消息,并且说拳击手在临死之前告知农场的同志们“动物农场万岁、拿破仑万岁,拿破仑永远正确”。又过了几年之后,动物们都到了原来约定的退休时间但是似乎没有动物能真的退休。同时动物们还发现猪们开始用后退走路,前腿夹着一条鞭子。此时猪们似乎更像人了。此时年老的动物们发现动物农场中《七戒》的其他几条都消失了,只剩下一条“凡是动物一律平等,但是有的动物比其他动物更平等”。在夜晚,动物们趴在墙头发现拿破仑与人类正在饮酒。故事在这个高潮中结束了,最后的一句结束语写的十分震撼人心“敢情动物们从窗外朝里看,目光从猪移动到人,再从人移动到猪,又从猪移动到人,要分清哪张脸是猪,哪张脸是人已经不可能了!”本文是乔治奥威尔讽刺集权主义的反乌托邦小说,在阅读的过程中我见识到了一个屠龙者终成恶龙的故事,见识到了集权者对人民的愚弄,舆论的管控,以及它们可笑的面孔。这个故事中极权主义的框架又在他的另一本书《1984》中被发扬光大。
2025年08月31日
3 阅读
0 评论
0 点赞
2025-08-31
手撕包菜
首先调一个酸辣汁:小半勺盐小半勺糖两勺生抽半勺耗油半勺老陈醋一勺芝麻香油两勺清水8.小半勺的水淀粉制作:起锅烧油加入蒜片、姜片、葱段以及几段干辣椒倒入手撕的包菜进行翻炒倒入之前调好的料汁5.翻炒之后盛出
2025年08月31日
3 阅读
0 评论
0 点赞
2025-08-24
读 《博格论指数基金》
本书的作者,约翰博格是指数基金之父。本书主要在强调一个主题,那就是从长期来看普通投资者投资被动指数基金的收益要大于投资主动型基金,原因主要有以下几点:相对与主动基金来说,被动指数基金的费用更低,而低费用经过长年累月的积累将是一大笔钱,如果按照收益来算相当于每年多出1到2个百分点的收益长期打败市场很困难,可能在短暂的时间内收益会超过市场的平均收益,但是投资者长期来看能获得与市场相同的收益也十分的不容易主动基金的高收益只是暂时的,未来大部分主动基金最多只能获得市场的平均收益;主动基金短期内的高收益有可能是市场过热的假象,而且主动基金一旦表现良好会导致大量投资者涌入,而主动基金的投资规则不允许基金经理留存大量的现金,导致这些现金必须投入市场有可能会高位接盘,最终在市场震荡向下时给投资者带来损失通过以上几点可以得出结论,普通投资者最好的投资方式就是投资低成本的指数基金。本书的内容十分的简单,但是书中会将一些概念反复的说,并且引用各种名人点评来为这些观点进行论证,虽然可以提到可可信度,但是不免显得有些啰嗦,其实我读这本书主要希望看到作者从他的角度聊聊指数基金的一些常识以及挑选指数基金的方式,没有看到这些我有些失望,也是我不太喜欢这本书的一个原因。但是书中对于投资也给出了一些名言警句,值得反复阅读:股市中价值和价格的关系就像是遛狗时人和狗的关系。价格有时高于价值,有时低于价值,但迟早会回归价值忽略金融市场上的那些短期噪声,关注企业经营的长期状况。想要投资成功,就要摆脱股票价格的预期市场,融入企业的真实市场。当我们试图战胜市场的时候……为了战胜市场而耗费的成本,很有可能会让我们成为输家投资中,真正的钱是创造出来的—就像我们最初用汗水赚到的那笔钱一样,真正的财富不可能来自买卖,只能源于买入证券并长期持有,收取利息和红利,从而实现价值的增长。如果你面前出现了一顿貌似免费的午餐,除非你有足够有说服力的证据,否则它就不是免费的
2025年08月24日
2 阅读
0 评论
0 点赞
2025-08-17
读 《手把手教你读财报》
最近在研究股票投资相关的内容,研究公司阅读财报是必须要经历的步骤。我虽然读过一些财报方面的书,掌握了一些理论,但是一旦遇到真正的财报发现理论与现实还是有一些差距的。介绍财报的书上来就是三大报表:资产负债表、利润表和现金流量表。但是真实的财报不光有这些财务报表,还有重要事项提示、公司情况说明、董事会针对未来公司的一些说明等等。这些信息该如何理解,如何结合财务报表来看这些数据呢?并且公司的财务报表中的科目与之前教科书上的说法有些不太一样。我急需一本能结合具体财报来讲解如何阅读财报、如何根据财报来评估公司的书,碰巧这本《手把手教你读财报》满足我的需求作者在副标题就开门见山的说,财报是用来排除企业的,财报不合格,不清晰的,或者对财报有疑问的应该优先排除利用财报排除企业优秀的企业各有各的优点,而垃圾企业的财报却有一些相似。我们通过阅读财报能首先排除一些不值得投资的企业,根据本书的内容,财报有问题的企业大致有下面的一些问题:无法按时发布年报第三方独立的会计事务所未出示标准无保留意见资产无法核算,例如书中举例养鱼池中的鱼鳖无法核算只能通过进货的发票来计算,存在大量的造假空间跨界开展业务的,比如原来是做食品行业的,最近看到ai比较火慢慢转入到ai行业公司突然改变会计政策,例如改变折旧计算的规则或者更改会计事务所账上没几个钱还容忍其他企业长时间欠款存货周转期变长但是伴随着营业额增加存货在销售额未增加的情况下大量增加,有可能是货卖不出去了公司的利润主要来自于偶然的营业外收入长时间经营现金流为负的需要持续大量现金投入才能产生利润的企业,虽然看着利润或者经营性现金流很多,但是扣除来年的投入实际没剩多少在建工程持续投入增大并且长时间没有看到回报管理层变化巨大,董事会集体辞职优秀企业的财报特征“其他应收款”和“其他应付款”科目涉及金额极小,甚至为零有息负债率低。(原则上说,如果有息负债率超过总资产的60%,企业算比较激进)轻资产公司优于重资产公司。【“当年税前利润总额/生产资产”,得出的比值如果显著高于社会平均资本回报率(按银行贷款标准利率的两倍毛估),则属于“轻公司”,反之则属于重公司。】选择高毛利率的企业。一般来说,毛利率能保持在40%以上的企业,通常都具有某种持续竞争优势。费用(销售费用、管理费及正的财务费用之和)能够控制在毛利润的30%以内,就算是优秀的企业了;费用超过70%的企业关注价值不大。如果只用一个指标来衡量企业的优劣,净资产收益率(ROE)是首选企业现金流肖像中,选择“老母鸡型”和“奶牛型”这两类重点关注。(老母鸡型企业:经营活动的现金流有流入、投入活动的现金流入、融资活动的现金流流出,一般这类企业可以靠经营挣钱并且在通过股利分红来回馈股东或者还债;奶牛型企业:经营活动的现金流流入、投资活动的现金流流出、融资活动的现金流流出;这类企业经营不错并且有计划增加投资来扩大生产以其未来有更好的营业收入,并且融资活动的现金流流出说明在还债或者回馈股东)虽然我总结一些特征,并不是说要严格按照这个标准来筛选企业,按照本书副标题——财报是用来排除企业的,在阅读财报的时候应该假设这份财报有问题带着怀疑的眼光来看,对每个数据多留点心,稍微有疑问的应该去财报中尝试找到解释,一旦发现解释不了或者你不信任财报中给出的解释,那么它就属于垃圾企业,不值得投资
2025年08月17日
2 阅读
0 评论
0 点赞
2025-08-11
wsl 启动报错:Wsl/0x80080005
周末结束过来上班的时候发现公司电脑上安装的wsl2 中的arch和Ubuntu 都无法打开了,表现出来的现象是通过终端打开系统时长时间无法进入系统,等待大概半小时左右会出现提示:Wsl/0x80080005通过网络上查找,这种一般是系统坏了,或者是服务没启动,又或者是网络协议栈出现问题。对应的办法就是重置Linux系统(这种是最坏的情况,一般留到最后实在没办法了再尝试)、启动 LxxManager 服务,重置网络协议。通过尝试我发现我的属于网络协议栈问题,通过powershell 命令(需要管理员权限)netsh winsock reset # 重置网络套接字 netsh int ip reset # 重置 IP 协议然后重启电脑问题就解决啦!
2025年08月11日
6 阅读
0 评论
0 点赞
2025-08-08
Emacs 折腾日记(二十九)—— 打造C++ IDE
在介绍vim配置的时候介绍过lsp的相关基础知识。简单来说lsp是一个协议,它以C/S架构的形式进行组织,lsp负责分析语法,给出具体的语法单元,完成跳转等功能的核心实现。而客户端则负责接收用户的操作请求并呈现具体结果。这样做的好处是将核心服务和客户端显示分离出来,核心部分重用,客户端则可以由各个编辑器自己实现,使各种编辑器都有相同的核心功能体验。对于Emacs来说,由lsp-mode 提供核心客户端库,管理服务器生命周期、消息路由及基础功能。另外也有 lsp-ui 这种增强UI模块,提供实时信息侧边栏(lsp-ui-sideline)、代码透镜(Code Lens)、悬浮文档等下面来介绍如何使用它们配置一个基础的lsp功能lsp-mode根据官方给出的配置,我们可以组一个基础的配置(use-package lsp-mode :ensure t :init ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") (setq lsp-keymap-prefix "C-c l") :hook ( ;; if you want which-key integration (lsp-mode . lsp-enable-which-key-integration)) :commands (lsp lsp-deferred))这里我们只是安装了一个客户端,想要真正实现lsp的功能,还需要针对具体的语言下载一个服务端,可以通过 lsp-install-server 来下载如果我们希望能像vscode那样,以悬浮窗口的形式显示符号的定义、声明或者注释文档,那么我们需要使用 lsp-ui 这个插件(use-package lsp-ui :ensure t :after (lsp-mode) :config (setq lsp-ui-doc-position 'top))这里我通过 lsp-ui-doc-position 来定义显示的窗口在上方,一般的编辑器默认是显示在光标所在的位置,但是我觉得显示在光标位置会影响我阅读后续的代码,所以我将它显示在上面,如果各位读者希望它像其他编辑器那样显示在光标位置可以修改参数为 at-point项目管理上述的lsp配置完之后,它只能使用当前buffer中的内容进行语法补全提示,也就是说我在其他的位置定义的函数和类在当前buffer中是无法识别到的。我们需要结合项目一起来使用。我们可以使用名为 projectile 的插件来进行项目管理(use-package projectile :ensure t :init (setq projectile-project-search-path '("~/projects/" "~/work/" "~/playground")) :config (define-key projectile-mode-map (kbd "C-c C-p") 'projectile-command-map) (global-set-key (kbd "C-c p") 'projectile-command-map) (projectile-mode +1)) (use-package counsel-projectile :ensure t :after(projectile) :init (counsel-projectile-mode))这里我们额外安装了 counsel-projectile 用来与 counsel 结合进行搜索语法检查语法检查方面,目前主流的插件是 flycheck 和 flymake,但是好像 flycheck 使用的人多一些,所以这里我也采用 flycheck。(use-package flycheck :ensure t :config (setq truncate-lines nil) ; 如果单行信息很长会自动换行 :hook (prog-mode . flycheck-mode))这里我们仅在编程的时候开启语法检查。同样的, flycheck 是一个前端,用来显示结果的,具体检查的核心功能是通过后端来实现的。后端的程序可以在官方网站上找到。状态栏显示相关的lsp信息现在是时候来修改以下状态栏的显示了,根据配置vim的经验,我还是希望主要显示当前编辑的模式、文件名、文件编码、lsp服务器、语法错误信息等。这里我使用 doom-modeline 来完成这个功能(use-package doom-modeline :ensure t :init (doom-modeline-mode 1) :config (setq doom-modeline-height 30) (setq doom-modeline-bar-width 5) (setq doom-modeline-icon t) (setq doom-modeline-lsp t) (setq doom-modeline-major-mode-icon t) (setq doom-modeline-buffer-state-icon t) (setq doom-modeline-buffer-file-name-style 'truncate-with-project) (setq doom-modeline-check-simple-format t) )通过上述代码来简单的配置一下,就可以有丰富的显示信息每种语言都对应了一个lsp的后端程序,lsp-mode官方网站 给出了每种语言对应的lsp后端程序,我们可以使用 lsp-install-server 来安装,这里我准备安装 clangd 这个后端在安装了lsp之后,再次打开一个cpp文件,可以发现它的界面如下:上面我们完成了lsp配置的基础准备工作,下面将要来针对具体的语言探索一下实际的使用方式和使用体验状态栏下分别显示了当前的模式(N代表normal模式)、文件类型、文件名称、当前编码方式等等,最后一个是flycheck 语法检查的结果,这里的代码比较简单,所以它没有检测出来任何问题,最后以绿色圆圈中的一个勾来显示。需要注意的是状态栏中的小火箭表示lsp服务已启用,如果没有这个标志可以手动的执行 lsp 命令选中项目的根目录C++ 项目实例C/C++ 项目需要明确的编译信息,clangd 通过 compile_commands.json 文件获取这些信息。对于cmake构建的项目cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1另外我希望每种语言对应的lsp配置放入到不同的配置文件中,做到模块化处理,因此我在配置中新建了一个lsp目录,并且按编程语言每种语言一个配置文件。目前c++语言的配置如下:(require 'lsp-mode) (add-hook 'c++-mode-hook (lambda () (setq lsp-project-identification-methods '(:root ("compile_commands.json" ".git" ".clangd" "CMakeLists.txt" "Makefile"))) (setq lsp-clients-clangd-args '("-background-index" "--clang-tidy" "--completion-style=detailed")) (setq-local completion-at-point-functions '( cape-file cape-keyword cape-dabbrev)) (lsp-deferred))) (provide 'cpp)为了实现不同的语言加载不同的配置,这里通过对应模式的hook来实现。一般每种模式都有一个对应的hook变量,它里面保存了一个函数,当启用该模式时会执行对应的代码,这里c++-mode 对应的是 c++-mode-hook。在这个hook中,主要做了四件事:第一,我们定义了项目根目录的标识;第二,定义了clangd启动的一些参数;最后也是最关键的一点,我们重新定义了补全端的函数。在配置Emacs的补全时,提供了一大堆补全方式,很多在编程时是用不到的,而且Emacs在补全时会依次根据 completion-at-point-functions 列表中保存的补全函数来查找补全项,一旦前一个函数返回了补全项,那么就不再往后查找。在编程的过程中前面定义的很多补全功能并没有lsp提供的补全好用,而且还会影响lsp的补全导致它出不来,所以我们去掉一些没用的,仅仅保留关键的部分。lsp-mode 会提供一个名为 lsp-completion-at-point 的补全函数注册到 completion-at-point-functions 中,因此这里我们不需要单独的写出来,当然写出来也没问题。我们可以通过 describe-variable 命令来查看 completion-at-point-functions 的值。Its value is (lsp-completion-at-point cape-file cape-keyword cape-dabbrev) Local in buffer main.cpp; global value is (cape-line cape-elisp-symbol cape-dict cape-ispell cape-keyword cape-file cape-dabbrev tags-completion-at-point-function) 最后一件事就是调用 lsp-deferred 来延迟加载lsp。因为 lsp-deferred 需要等到缓冲区完全加载完成之后才加载,所以将它放到最后面代码跳转在vim中,有几个关于跳转的关键的快捷键,gd 表示 goto declaration 跳转到定义,gD 表示 goto definition 跳转到定义,使用 gf 来跳转到头文件,跳转之后可以使用 ` 再次回来,这些快捷键 evil` 也为我们保留了,我们不需要额外的配置只要lsp能加载起来就能使用。显示符号文档信息vim配置中定义了 gh 显示符号的文档信息,我们可以使用 define-key 来定义快捷键。既然显示文档的功能由 lsp-ui 来提供,这里就将代码放入到 lsp-ui 位置(define-key lsp-ui-mode-map (kbd "gh") #'lsp-ui-doc-glance)tree-sitter在配置vim的时候提到过tree-sitter 是轻量级的语法分析器,而lsp是进行语义分析的重量级工具,tree-sitter 是对 lsp 的一个补充,并且我们用tree-sitter 进行了语法高亮和代码片段的折叠,这里尝试在Emacs中使用tree-sitter(use-package tree-sitter :ensure t :hook (prog-mode . tree-sitter-hl-mode) ;;启用语法高亮 :config (global-tree-sitter-mode)) (use-package tree-sitter-langs :ensure t :after tree-sitter)安装完成之后,我们通过命令 tree-sitter-langs-install-grammars 来安装对应的语言支持,默认是安装所有语言的支持,这里我就使用默认的就好下面尝试启用在vim中 zc、和 zo的功能。它们主要是用来折叠和展开代码块。我们来安装一个名为 ts-fold 的插件,该插件没有被放入到 elpa,所以需要手动下载然后加载(use-package ts-fold :load-path "~/.emacs.d/ts-fold" :config (global-ts-fold-mode 1) (with-eval-after-load 'evil (evil-define-key 'normal 'global "zc" #'ts-fold-close "zo" #'ts-fold-open)))最终的效果如下:基于tree-sitter,我们还可以实现一个非常重要的功能——增量选择代码块。在vim配置中我使用回车来扩大选区,使用退格键来减小选区,这里仍然沿用这种配置增量选择的功能可以使用 expand-region(use-package expand-region :ensure t ; 从ELPA自动安装 :bind ("C-=" . er/expand-region) :config (defun my/incremental-expand-region() (interactive) (if (region-active-p) (er/expand-region 1) (er/mark-word)) (setq deactivate-mark nil)) (defun my/contract-region() (interactive) (if (region-active-p) (er/contract-region 1) (call-interactively 'evil-backward-char))) (with-eval-after-load 'evil (dolist (state '(normal visual motion)) (evil-define-key state 'global (kbd "RET") nil) (evil-define-key state 'global (kbd "<backspace>") nil)) (evil-define-key 'normal 'global (kbd "RET") #'my/incremental-expand-region) (evil-define-key 'normal 'global (kbd "<backspace>") #'my/contract-region)))原版的增量选择,如果没有选中某个部分无法执行增量,所以对它进行稍微的改造,如果当前没有选中任何部分,先选中当前光标所在的单词。然后继续进行增量选择。与增加选区类似的,减少选区也是先判断如果已经没有选中区域的话还是延续vim中退格键的功能。本篇到此就先结束了,但是我们的IED的功能并没有配置完,后面我计划加上自动编译运行、调试等功能,这些就在后面的文章中给出
2025年08月08日
8 阅读
0 评论
0 点赞
2025-07-11
Emacs折腾日记(二十八)——代码片段
在前面的章节中,介绍了 vertico 体系的补全,已经实现了在各个buffer中的补全功能,但是作为程序员,使用Emacs主要用来编程,对于编程来说上述的补全体系仍然不够完整,我们还需要基于lsp的补全以及基于代码片段模板的补全,这里先介绍代码片段。在之前写vim的配置时已经介绍过代码片段的概念以及基于vim 的配置,感兴趣的读者可以自行在我往期的博客中寻找,这里就不对它进行详细的介绍了。直接来使用它。在Emacs中,我们使用插件 yasnippet 来支持这个功能(use-package yasnippet :ensure t :hook ((after-init . yas-reload-all) ((prog-mode LaTeX-mode org-mode) . yas-minor-mode)) :config (setq yas-snippet-dirs '("~/.emacs.d/snippets")))我们通过上面的代码就能把它启用起来,yas-reload-all 表示在Emacs启动时重新加载所有已启动的代码片段;yas-minor-mode代表启动代码片段补全的功能。但是我们做了限制,只在编写代码、LaTeX和org-mode 文件时启动。如果各位读者希望在markdown 中也启动的话,也可以加上 markdown-mode 的选项。但是既然使用了Emacs,当然要用比 markdown 更加强大的 org-mode 了现在Emacs已经支持了代码片段,它的快捷键与vim中的一致都是使用tab 来进行补全。那么接下来就是通过代码片段文件来提高我们编程的效率了。添加代码片段文件我们可以使用已经写好的,也可以自己根据自己的习惯来定制。下载通用的代码片段官方虽然提供了一些代码片段,但是数量较少,使用起来并不那么方便,我们可以下载网络上的一些公共库来丰富我们的代码片段。这里我介绍一下 Doom Emacs Snippets Library。它是专门为doom emacs 用户打造的代码片段库,使用者不少。其他的代码片段库的安装与使用与它类似,读者可以依葫芦画瓢来安装。 首先找到官方的代码仓库,然后将它克隆下来,我将它放到 ~/.emacs.d/emacs-snippets 目录中。然后通过(use-package doom-snippets :ensure nil :load-path "~/.emacs.d/doom-snippets" :after yasnippet)来加载它。之后需要 Yasnippet 插件能找到这个目录,所以我们修改一下上面的配置(use-package yasnippet :ensure t :hook ((after-init . yas-reload-all) ((prog-mode LaTeX-mode org-mode) . yas-minor-mode)) :config (setq yas-snippet-dirs '("~/.emacs.d/snippets" "~/.emacs.d/doom-snippets"))) ;; 添加一行代码片段的加载路径此时再编写代码发现多了一些代码片段自定义代码片段与 doom emacs snippets library 代码片段类似,我们也需要按照具体的mode来组织代码片段的文件目录。每一个关键字一个文件例如~/.emacs.d/snippets/ ├── python-mode/ │ ├── for ; for 循环模板 │ └── class ; 类定义模板 └── c++-mode/ └── foreach ; for-each 循环模板有了这些准备的前提条件,我们可以自行创建自己的代码片段了。在emacs 中执行 yas-new-snippet 可以打开一个新的buffer,并显示代码片段的模板# -*- mode: snippet -*- # name: # key: # -- name后面跟着的是代码片段的名称,在补全时会以补全项显示这个名称;key代表关键字,表示用哪个缩写来触发。例如我们定义一个 prt 来展开成 printf 语句,那么就可以写成 name:prt key: prt尝试生成第一个代码片段后面的写具体展开的代码,例如我们编写一个自动生成hello world的模板# -*- mode: snippet -*- # name: create-hello # key: hello # -- #include <stdio.h> int main(int argc, char* argv[]) { printf("hello world\n"); return 0; } 在编写完成之后使用快捷键 C-c C-c 来保存,Emacs在保存时会让你输入对应的 mode 并且给出需要保存的位置。当我们修改完适用的 mode 和 保存的位置之后,我们发现它在对应位置生成了文件。重启Emacs或者 使用命令 yas-reload-all 来重新加载所有的代码片段。之后输入hello就可以看到它为我们生成了 c 版本的 hello world 程序占位符我们希望的代码大体上不变但是关键地方由我们自己来填充,这个时候可以使用占位符。占位符的格式为 ${} 大括号中填入数字序号。或者使用 ${1: default} 来表示这个位置默认填写default字符。下面是一个具体的例子# -*- mode: snippet -*- # name: qt-class # key: qcls # -- class ${1} : public ${2:QObject} { Q_OBJECT public: ${1}(${2}* parent = nullptr); ${1}(const ${1}& other); ${1}& operator=(const ${1}& other); ~${1}(); signals: slots: protected: }上面我们定义了一个快速生成继承自 QObject 类的子类的模板,上面有两个占位符,第一个占位符表示名称,它没有默认值,一旦确定了它的也就是类型,它会自动生成类的无参构造、拷贝构造、赋值运算符重载和析构函数的定义。第二个占位符指出了它的父类,它的默认值是 QObject 类,它的效果如下使用elisp代码生成动态信息我们可以使用 `` 来包裹elisp代码,生成动态信息。一般在C/C++ 代码的头文件中会包含一些注释信息,用来说明文件的用途包含的接口信息等等。我们希望生成这么一段注释的代码片段# -*- mode: snippet -*- # name: Custom File Header # key: hdoc # -- /** * @file `(file-name-nondirectory (buffer-file-name))` * @bref ${1:brief description} * @details ${2:detailed explanation} * @date `(format-time-string "%Y-%m-%d")` * @commit history: * \t v${3:1.0}: ${4:Initial version} */ $0上面我们使用 elisp代码 (file-name-nondirectory (buffer-file-name)) 来获取对应的文件名,通过 (format-time-string "%Y-%m-%d") 来获取时间。并且最后使用 $0 来将光标定位到这个位置,这个位置将会在我们使用tab处理过所有tab之后自动跳转。本文到此就结束了。本文主要介绍了在Emacs中使用代码片段,并且介绍了编写代码片段的一些方式。有了这些在编写代码时会更加得心应手。
2025年07月11日
8 阅读
0 评论
0 点赞
2025-07-10
读 《指数基金投资指南》
之前接触过基金,也买过基金,有过亏损,在最近这两年才慢慢开始盈利。我不知道为什么会亏损也不知道为什么会盈利。甚至对于基金的一些概念都不太了解。这本书正好补充有关基金方面的知识。什么是指数基金巴菲特在公众场合唯一公开推荐的投资方式就是定投指数基金。那么什么是指数基金呢。要理解指数基金先来了解什么是基金。简单理解,基金就是一个篮子,里面可以按照预先设定好的规则,装入各种各样资产。装入股票的是股票基金、装入债券的是债券基金、二者都有的被称之为债券基金、装入各种短期债券、短期理财、现金,就是货币基金。基金分为主动型基金和被动型基金。主动型基金就是由基金经理主动的帮助我们挑选股票或者债券。而被动型基金也就是指数基金,指数基金的关键是按照指数被动的选择投资的标的。那么什么是指数呢?指数是一个选股规则,它的目的是按照某个规则挑选出一篮子股票,并反映这一篮子股票的平均价格走势。说起来有点抽象,但是在日常生活中我们早就用到了指数这一概念,在上学时我计算各科考试的总成绩并根据这个分数来排名,这个计算成绩的方式就是成绩的指数。我们也可以单独列出某一科的成绩,例如语文或者数学,这个分数就是语文或者数学分数指数。资本市场上对各个资产几乎都有一个指数,也就是都有一套选择标准来衡量该资产在资本市场的整体表现,而指数基金就是按照这个指数的编制规则来组织资产进行投资。说它是被动基金是因为它选择投资的股票或者债券等都是按照指数的规则来编制不需要基金经理进行额外的研究。为什么选择指数基金进行投资呢首先指数的编制标准是公开的,它的业绩与基金经理无关。它反映的是市场的平均水平,而越是规范的市场主动型基金的收益最终都会回归到市场的平均水平。主动型基金的收益主要看基金经理的投资水平,而基金公司经常干的就是通过明星基金经理来发行新基金,在基金规模大了之后更换基金经理。而指数基金不存在这个问题。指数基金“长生不老”,个股有退市的风险,而指数基金会根据指数规则动态的调整持有的股票,不存在这个问题指数基金长期来看是上涨的,指数基金反映的是市场的经济水平,随着国家经济水平的提高,指数也会水涨船高。股神巴菲特也提到过,买指数基金就是买国运。只要相信国家能继续发展,指数基金就能长期上涨,我们就能分享国家经济增长的收益指数基金的成本低,因为它是被动的,不需要基金经理操心,它的管理费、申购赎回费等比主动型基金便宜。基金的费用一般有:管理费:管理费是基金公司收入的主要来源。主动型基金一般会收取基金规模的1.5%作为管理费,指数型一般是 0.5%托管费:托管费是交给基金的托管方的。基金的庞大资产,并不是直接存放在基金公司,一般会在第三方托管方,例如某家大型银行。申购和赎回费:买入和卖出的费用市面上常见的指数基金有哪些指数基金最常见的一种分类,就是分为宽基指数和行业指数。有的指数基金在挑选股票的时候,并不限制非得是投资哪些行业,这种被称为宽基指数;但有的指数基金在挑选股票的时候,会要求只投资哪些行业的股票,这种被称之为行业指数。宽基指数上证50:上证50指数是从上交所挑选沪市规模最大、流动性好、最具代表性的50只股票组成样本股,以综合反映沪市最具影响力的一批优质大盘企业的整体状况。特点之一:以大盘股为主。或者说以蓝筹股为主,什么是蓝筹股?蓝筹这个词来自西方赌场。在西方赌场里,一般有三种颜色的筹码,其中蓝色筹码最为值钱。后来就用蓝筹股,代表规模较大、有较大影响力的公司。特点二:只有上交所的股票,没有深交所的股票。沪深300指数:是由中证指数公司开发的,从上交所和深交所挑选规模最大、流动性最好的300只股票。特点:沪深300以大盘股为主,兼顾上海和深圳上市公司。中证500指数:将全部沪深300指数的300家公司排除,然后将最近一年日均总市值排名前300名的企业也排除,这样可以最大限度地避免选入大公司。在剩下的公司中,选择日均总市值排名前500名的企业,这就是中证500指数啦。中证500本身是以中型上市公司为主。我们都知道国内有上交所和深交所,我们平时说的股票,其实说的就是在这两个证券交易所上市交易的股票,它们大多在主板上市交易。在主板上市交易,门槛是很高的,公司需要达到一定规模,而且也要有足够的盈利才可以。但是有一些小公司,目前盈利还不好,达不到主板上市的条件。国家就给这类公司提供了一个门槛更低的市场:创业板市场。创业板市场是放在深交所下面的。创业板指数:创业板指数是为了衡量创业板最主要的100家企业的平均表现而设立的,只从创业板上市公司中,挑选出规模最大、流动性最好的100只股票。创业板综指:创业板综指是为了衡量创业板所有上市公司的股价平均表现而设立的。它包括创业板全部的500多家企业。这两个指数相比之前的主板指数,更容易暴涨暴跌,在投资时要有心理准备上面介绍的指数采用的是市值加权的方式,市值加权也就是市值越大权重就越大。红利指数采取的是策略加权的方式编制。红利指数采用红利策略来编制,所谓的红利就是上市公司盈利之后通过分红的形式将利润返还给投资者。有研究表明,能实现高现金分红的股票,长期持有的平均收益率高于现金分红低的股票上证红利指数:这个指数挑选了上交所过去两年平均现金股息率最高的50只股票中证红利指数:中证红利指数由中证指数公司编制,同时从上交所和深交所挑选过去两年平均现金股息率最高的股票,成份股数量扩大到100只深证红利指数:深证红利指数与上证红利指数对应,专门投资深交所的高现金股息率的股票,不过成份股只有40只红利机会指数:这是标普公司围绕A股开发的红利指数。红利机会指数在传统红利指数的基础上增加了一些筛选条件。传统的红利指数,一般只是挑选高股息率的股票,没有其他的要求。但是红利机会指数有3个要求:过去3年盈利增长必须为正;过去12个月的净利润必须为正;每只股票权重不超过3%,单个行业不超过33%。红利指数的特点之一:高股息率,在熊市更有优势;特点之二:能持续发放现金股息的公司,盈利能力和财务健康状况好的概率越高;特点之三:提供分红现金流我们经常能听到基本面这个词。基本面覆盖了一个公司的运营的各个方面,比如说营业收入、现金流、净资产、分红等。通过基本面来选股,也就是说,谁的基本面更好,谁占的权重更高。那我们怎么知道一个企业基本面的好坏呢?目前一般从4个维度去衡量:营业收入,现金流,净资产和分红。而基本面指数也正是从这4个维度去挑选股票的在国内最出名的就是中证基本面50指数。这个指数是按照4个基本面指标,挑选出综合排名前50的公司。具体来说,是从上市公司过去5年的年报数据中,计算4个基本面指标。营业收入:公司过去5年营业收入的平均值。现金流:公司过去5年现金流的平均值。净资产:公司在定期调整时的净资产。分红:公司过去5年分红总额的平均值。这种按照占总规模百分比来排名得分的方式,很明显公司规模越大,越占优势。所以基本面50指数挑选出来的,往往也是大盘股。从定位上来说,基本面50指数跟上证50指数很相似。不过因为它综合考虑了收入、盈利、净资产等基本面因素,所以挑选股票时会考虑得更全面一些。央视财经50指数,它是一种专家加权的指数。它是深证指数和央视的财经频道联合推出的。简单说,央视50指数就是专家们投票选出来的50只股票。它和前面介绍过的指数都不太一样:一般的指数,它们的选股规则是透明的,已经写在纸面上的,但是央视50指数是依靠专家们的选股能力来选股的,其规则并不透明,是一种很特殊的指数恒生指数:国内除了上海和深圳两个证券交易所之外,还有一个非常特殊、但又非常重要的证券交易所—香港证券交易所,简称港交所。在港股指数基金中,最著名的就是恒生指数了。特点之一:历史悠久,成熟开放。特点之二:跟内地紧密相关,但投资者以境外投资者为主。特点之三:“老千股”导致个股投资风险巨大,普通投资者投资港股的最好方式—港股指数基金。H股指数:如果一家公司在内地注册,但是在香港地区上市,这样的公司就是H股了。为了衡量这些公司股票的表现,恒生指数公司编制了恒生中国企业指数,也就是通常说的国企指数,简称为H股指数。这里的国企并不是我们理解上的国企,这里指的是在国内营业但是在香港上市的企业。特点之一:内地公司在境外的“代言人”。特点之二:与内地经济紧密相关,但仍然是以境外投资者为主。特点之三:H股与A股指数的亲密关系。上证50AH优选指数:如果A股和H股差价过大,那么相对便宜的那个未来的收益会更好。这就是AH股轮动策略:买入AH股中相对便宜的那个,卖出相对贵的那个。特点之一:成份股与上证50相同。特点之二:成份股入选50AH优选指数时,如果成份股同时具备A股和H股,选相对便宜的那个。特点之三:每个月第二个周五,进行一次轮动。纳斯达克100指数:纳斯达克100指数投资的是纳斯达克规模最大的100家大型企业标普500指数:标普500指数是美国影响力最大的一个股票指数,是美国传统经济的代表,定位上类似于国内的沪深300指数上证综指:综指指的是综合指数,上证综指包括了上交所全部的上市公司,目的是反映上交所所有股票的走势。中证100指数:中证100指数是从沪深300指数中,再挑选出规模最大的100只股票组成的。比起上证50指数,它覆盖了深交所的大公司,所以更加全面一些中证800指数:中证800指数=沪深300指数+中证500指数;中证1000指数:追踪除去中证800指数之外最大的1000只小盘股行业指数最主要的10个一级行业分别是:材料:金属、采矿、化学制品等。可选消费:汽车、零售、媒体、房地产等。必需消费:食品、烟草、家居等。能源:能源设备与服务、石油天然气等。金融:银行、保险、券商等。医药:医疗保健、制药、生物科技等。工业:航空航天、运输、建筑产品等。信息:硬件、软件、信息技术等。电信:固定线路、无线通信、电信业务等。公共事业:电力、天然气、水等。值得投资的行业,主要有两个,一个是天生赚钱更容易的行业,另一个是具有明显强周期性的行业。投资医药股和必需消费股,长期来看在A股更容易赚钱。市场需求比较稳定,企业有护城河能保证一定的利润率,并且再投资需求小,能获得大量的自由现金流,只有容易形成这些条件的行业,才能比较容易的赚钱。如果在二级市场投资这样的企业,想赚钱还要添加一个条件:企业愿意回馈股东,而不是乱花钱。强周期行业,如果在周期底部投入,在顶部卖出也能获取很好的收益必需消费行业也被称为日常消费行业、主要消费行业。必需消费,主要是维持我们正常生活所需要的各种消费品,例如饮料、酒、农副食品等。目前消费行业指数主要有:上证消费指数:从上交所挑选必需消费行业公司。上证消费80指数:从上交所挑选80家规模最大的必需消费行业公司。中证消费指数:从中证800,即沪深300和中证500中挑选必需消费行业公司。全指消费指数:从所有上市公司中挑选必需消费行业公司,覆盖范围最广目前医药行业的指数主要有以下几种:中证医药指数:又称中证800医药指数,是从中证800指数中挑选医药行业。中证医药100指数:挑选了100家大型医药股,每只股票买入相同的金额。上证医药指数:只投资上交所的医药行业公司。全指医药指数:从整个A股中挑选医药行业,它覆盖的医药公司是最全的。细分医药指数:挑选了医药行业细分领域的主要公司。300医药指数:挑选了沪深300指数里的医药行业公司。500医药指数:挑选了中证500指数里的医药行业公司。强周期行业主要有银行、证券业、地产行业目前国内的银行业指数基金,基本上都是追踪中证银行指数;证券行业的指数基金,追踪的基本都是中证全指证券行业指数目前国内的地产行业指数一共有三只,即中证800地产指数、国证地产指数和地产等权指数。其他行业指数主要有:中证军工指数中证环保指数中证白酒指数追踪这些指数的基金有多个,很多时候我们根据基金名称就能看出它追踪的是哪个指数。例如 易方达沪深300ETF联结A。这个名字包含了这些信息:易方达是发行基金的机构名称沪深300代表它追踪沪深300指数EFT 表示场内交易型基金,基金一般分为场内和场外基金,场内基金是需要在券商处开通交易所账号,并在交易所交易。场外基金则在交易所之外可以直接在支付宝或者微信上购买联结,表示他实际是在投资场内的ETF基金A,表示基金类型;一般基金有A类和C类。A类基金适合长期持有,C类则适合短期做波动一般指数基金的命名都是采用这种形式:发型机构|追踪指数指数|交易类型|联结。其中后面两项可能不是不需要的。交易类型有EFT、QDII、LOF、FOF;其中QDII是为了投资海外,基金公司专门申请外汇额度并且将投资者的钱转化为外币进行海外市场的投资。这种类型的基金容易受到外汇额度的影响。LOF表示可以场内交易也可以场外交易。FOF表示它是基金的基金,它的主要投资标的是投资各种基金。如何投资指数基金投资指数基金主要采用价值投资的理念。价值投资总结起来有三点:股票有其内在价值,股票的价格围绕其内在价值上下波动能力圈理论,要求我们对所投资的品种非常了解,能判断出它大致的内在价值是多少,而不是什么热门投资什么安全边际,就是说,我们要用比价值更低的价格去买股票。为了确认股票的实际价值,需要对它进行估值,主要估值模型有:市盈率:公司市值/公司盈利(即PE=P/E,其中P代表公司市值,E代表公司盈利)。其中静态市盈率是取用公司上一个年度的净利润,滚动市盈率是取用最近4个季度财报的净利润,动态市盈率是取用预估的公司下一年度的净利润。市盈率反映了我们愿意为获取1元的净利润付出多少代价。市盈率的适用范围:流通性好、盈利稳定的品种。流通性越不好的股票,市盈率就越没有参考价值。这是因为当你想以这个市盈率去进行投资的时候,你的投资行为就会极大地影响市价,形成一种反馈效应。一般能够进入沪深300、中证500之类指数的股票,它们的流动性都没有什么问题。使用市盈率的第二个条件是盈利稳定。有的行业盈利并不稳定,不适用市盈率,例如有“市盈率陷阱”的没落行业和周期行业,有的行业处于成长期或者亏损期,也不适用市盈率。宽基指数基金大多都可以与这两点比较符合,所以使用市盈率为宽基指数基金来估值是可行的盈利收益率:盈利收益率是市盈率的变种。市盈率是用公司市值除以盈利,而盈利收益率则是用公司盈利除以公司市值。也就是盈利收益率=E/P。换句话说,盈利收益率也约等于市盈率的倒数。它所代表的意义是,假如我们把一家公司全部买下来,这家公司一年的盈利能够带给我们的收益率,就是盈利收益率。盈利收益率也是有适用条件的,市盈率所要求的流通性好、盈利稳定,盈利收益率也同样要求。市净率市净率指的是每股股价与每股净资产的比率,也就是我们说的账面价值。市净率的定义是:PB=P/B(其中P代表公司市值,B代表公司净资产)。净资产通俗来说就是资产减去负债,它代表全体股东共同享有的权益。说到市净率就不得不说到,净资产收益率(ROE):ROE等于净利润除以净资产。ROE越高的企业,资产运作效率越高,市净率也就越高。如果一个企业主要靠无形资产来经营,像律师事务所、广告服务公司、互联网公司,那市净率就没有多少参考价值了。当企业的资产大多是比较容易衡量价值的有形资产,并且是长期保值的资产时,比较适合用市净率来估值股息率股息,是投资者在不减少所持有的股权资产的前提下,仍然可以直接分享企业业绩增长的最佳方式。股息率是企业过去一年的现金派息额除以公司的总市值,而分红率是企业过去一年的现金派息额除以公司的总净利润。分红率一般是公司预先就设置好了,并且连续多年都不会有什么改变。股息率和盈利收益率之间有很大的关系。股息率=股息/市值,而盈利收益率=盈利/市值,分红率=股息/盈利,所以股息率=盈利收益率*分红率。所以对同一个指数来说,往往盈利收益率高的时候,也是股息率高的时候。这就是盈利收益率与股息率之间的关系。在投票时,交易软件或者网站都会给出这些指标。但是基金是一揽子股票,它可以把背后股票的盈利、净资产、股息等数据求出一个平均值,从而计算出指数基金的估值指标。查询这些可以在作者的公众号、指数的官方网站、第三方的数据网站进行查询。有了这些指标,我们就可以根据这些指标来挑选那些处于低估的指数。盈利收益率法我们可以根据盈利收益率来判断指数的估值。作者在书中给出了两个参考数据,当盈利收益率大于10%时开始定投,小于10%时继续持有,当小于6.4%时分批卖出。这两个数据源自格雷厄姆的价值投资理论,格雷厄姆认为满足两个条件就算高,一是盈利收益率要大于10%,二是盈利收益率要大幅高于同期无风险利率。这个无风险利率一般使用十年期国债利率作为参考。盈利收益率法只适合于流通性比较好、盈利比较稳定的品种。目前适合盈利收益率的品种,国内主要是上证红利、中证红利、上证50、基本面50、上证50AH优选、央视50、恒生指数和恒生中国企业指数等博格公式博格公式的创始人是指数基金之父——约翰博格。他经过长期研究发现决定股市长期收益的主要有三个因素:初始投资时刻的股息率、投资期内的市盈率变化、投资期内的盈利增长率。基于这三个因素,他提出指数基金未来的年复合收益率,等于指数基金的投资初期股息率,加上指数基金每年的市盈率变化率,再加上指数基金的每年的盈利变化率。第一个变量是股息率,这个在买入时可以查到。第二个变量是市盈率,一般来说A股股票的市盈率一般呈周期性变化。一般我们可以统计历史市盈率的变化范围,然后看当前市盈率在历史位置中处于何种水平。第三个变量是盈利变化率,对指数基金来说,只要国家经济长期发展,盈利就会长期上涨。只不过具体到某一段时间,盈利上涨的速度并不一样,我们也难以预测盈利的上涨,如果国家经济长期向上的话,这个值一般会增长,因此在一个经济持续上升的市场,这个值可以忽略。这就是格雷厄姆所说的,赚取市盈率上涨带来收益和初始股息率带来的收益。博格公式也有失效的时候,那就是上市公司的利润下降或者呈周期性变化的时候,市盈率计算公式中的每股收益就失效了。这种情况下,我们可以使用博格公式的变种,也就是使用市净率来对指数基金进行分析。市净率 = 股价 / 净资产。变化一下得到了股价 = 市净率 * 净资产。也就是在投资期间,股价变化主要取决于市净率和净资产的变化。这就是伯格公式的变种,指数基金未来的年复合收益率,等于指数基金每年市净率的变化率加上指数基金每年净资产的变化率。使用博格公式的变种还有一个前提条件。公司的盈利虽然不稳定,但是要求公司在经营困难的时候也不会亏损,这样,公司的净资产价值才会有保障,我们才可以使用市净率来对其进行估值。总结一下就是:针对长期稳定盈利的公司,可以采用盈利收益率法来判断估值;针对盈利呈高速增长并且有分红的公司,可以采用博格公式看股息率和市盈率来判断;针对盈利不稳定或呈周期性变化但是仍然能盈利的公司采用博格公式的变种,也就是市净率来估值;长期亏损的企业,直接远离针对指数基金,可以有这么一个表策略适用的指数基金盈利收益率上证50、上证红利指数、中证红利指数、基本面50、央视50、上证50AH优选、恒生、H股指数博格公式(市盈率版本)沪深300、中证500、创业板、红利机会指数、必须消费行业指数、医药行业指数、可选消费行业指数、养老产业指数博格公式(市净率版本)证券行业指数、金融行业指数、非银行金融行业指数、地产行业指数指数定投确定了要投资哪些指数基金,下面的问题就是如何投资呢?针对工薪阶层推荐采用定投的方式。如果定投那么定投的策略是什么呢?这里的策略主要是什么时候投入、投入多少钱、什么时候停止投入、什么时候卖出开始定投的时机根据上面给出的估值方法,在价格处于低估时买入、高估时卖出。针对盈利收益率法,在盈利收益率大于10%时开始定投、在10%到6.4%之间时停止定投、小于6.4%时卖出;针对博格公式法,可以结合历史数据来判断是否处于高估或者低估定期买入的方式定期买入的时机对于工薪阶层来说可以在发薪日之后的第一个交易日进行定投,就当存下一笔钱。可以定投固定金额,也可以根据估值来决定投资的金额,在估值偏低时多买入,偏高时少买。这种方式是一种定时不定额的投入定时不定额的投入方式,如果使用盈利收益率法来判断估值的话,我们可以使用下面的公式来决定下次投资多少$ 下次投入的金额 = 首次低估时投入金额 \times (\frac{当月的盈利收益率}{首次定投时的盈利收益率})^n $其中 n 是定投因子,由我们自己决定,假设n的值取1,首次定投时盈利收益率为 10%,首次投入的金额为1000万,那么根据公式可得:第二次定投时盈利收益率为 11% 的话: 1000 * 11 / 10 = 1100第二次定投时盈利收益率为 12% 的话: 1000 * 12 / 10 = 1200以此类推如果使用博格公式的话,可以通过下面的公式来计算$ 下次投入的金额 = 首次低估时投入金额 \times (\frac{首次定投时的市盈率}{当月定投时的市盈率})^n $$ 下次投入的金额 = 首次低估时投入金额 \times (\frac{首次定投时的市净率}{当月定投时的市净率})^n $构建自己的投资计划构建自己的投资计划首先要梳理自己的现金流即每月收入 - 必要支出 - 应急支出 = 投资的金额。用于投资的钱一定要是未来几年用不到的钱。因此这里除了支付衣食住行用等必要支出的钱以外,还需要保留一些钱作为应急支出。这部分用作应急的钱可以投入余额宝等货币基金。我们可以通过记账的方式来记录自己每一个月必要的支出,通过记账,我们可以知道“钱到底花在了哪里”;再通过分析开销,就可以知道“哪些不该花的钱可以省下。留出了投资的钱,下一步就是选择投资的基金了;可以使用上面介绍的方法来挑选低估的基金定期投入。接下来就是构建投资计划,确定每月的投资频率,可以选择每月投资或者每周投资,通过历史数据回测,每月投资与每周投资相比收益没有明显的差别,因此本书的作者推荐每月投资,每月在发薪日的下一个交易日投入一定的金额。开始定投之后需要定时优化投资策略,例如当指数高估时要停止定投或者卖出,低估时可以适当的增加投资。为了方便优化策略,需要每次记录定投的信息。我们可以创建下面的定投计划表定投计划表1.梳理现金流(1)我的家庭月收入是____元,家庭月开支是____元。每个月剩余资金____元(剩余资金=月收入-月开支)。(2)每个月的剩余资金____,我打算拿出____%的比例来定投(一般50%比较合适),也就是说,每个月我能用来定投指数基金的资金是____元。2.选择适合定投的指数基金通过 □公众号 或者 □指数网站,查找出当前处于低估、适合定投的指数基金有____只,分别是:____。□我的每月定投资金少于1000元,可以选1只,我选择____;□我的每月定投资金在1000~3000元或以上,可以选2~3只,我选择____,每只指数基金的定投金额分别为____。3.构建定投计划(1)寻找适合自己的定投渠道。□我有过投资股票的经验,熟悉场内操作,可以从场内入手,券商____是,使用的股票交易软件是____。□我是新人,刚开始接触定投,可以从场外开始入手,选择场外的定投平台是____。(2)确定每月的定投日期。我选择每月____日作为定投日进行定投,原因是(比如这是每月发工资后的第一天),将本月定投资金投入到低估值指数基金上。(3)列出投资策略。我的投资策略是:在指数基金低估的时候,坚持每月定投。在指数基金恢复正常估值的时候,坚定持有基金份额。到牛市指数基金高估的时候,分批卖出获利。有了上面的定投策略表之后可以使用下列的定投记录表来记录定投的信息日期操作(买/卖)交易品种(代码)买入或卖出金额成交单价买入和卖出的份额买入和卖出时的估值本书后面还有关于定投的心理建设,但是我觉得写的不够详细,如果想了解这方面的内容可以考虑看《小狗钱钱》或者《穷爸爸富爸爸》这些财商的书可能更好
2025年07月10日
10 阅读
0 评论
0 点赞
1
2
3
...
34