广告行业中那些趣事系列65:使用chatgpt编写基金定投程序
  dqHClNfrJu09 2023年12月01日 23 0


公众号:数据拾光者

摘要:本篇介绍了prompt生成器和使用chatgpt来编写一个基金定投程序。首先是背景介绍,我们在日常工作和生活中可以使用chatgpt来大大提升工作效率;然后介绍了prompt生成器的原理以及使用示例;接着重点介绍了使用chatgpt来帮助我们编写一个基金周定投程序,包括基金数据获取和设计prompt得到程序示例;最后通过数据分析验证普通散户通过合适的周定投策略的确可以在大A赚取到丰厚的收益,重点分析了止盈策略的重要性、设置不同年化率的影响以及周几对周定投的影响。对于希望使用chatgpt提升工作效率,尤其是对投资基金感兴趣的小伙伴可能有帮助。

下面主要按照如下思维导图进行学习分享:



广告行业中那些趣事系列65:使用chatgpt编写基金定投程序_ci

01 背景介绍

随着ChatGPT大火之后,如何高效的使用大语言模型可以直接提升我们的工作效率和生活品质。在实际工作项目中,我们已经用chatgpt来帮助我们给广告文案数据打标,帮助我们生成广告落地页(这里会涉及生成广告标题、正文、头图提示词等)。这两块的工作后续会找机会进行分享。除此之外,我也经常用chatgpt来帮助我实现一些功能性的代码,非常方便实用,只需要描述清楚你的需求,给定输入和期望的输出,就能得到对应的程序代码。虽然chatgpt大模型能力非常强,但是想要用好它却不是那么容易,需要注意提问的方式,也就是prompt提示词的设计。对于一些简单的问题也许不需要特别设计提示词,但是对于一些复杂问题,提示词质量的好坏直接决定chatgpt输出答案的好坏。

02 关于Prompt Creator

提示词生成器Prompt Creator核心思想是让chatgpt来帮助我们设计prompt,主要思路是让用户描述需求,然后通过用户-chatgpt问答的方式来把我们的需求具体化和定制化,从而帮助我们设计和完善prompt。

当我们遇到一个复杂的问题不知道从何下手的时候,可以利用chatgpt丰富的知识来帮助我们一步步把需要任务的方方面面都考虑进去,从而创建一个具体、明确的prompt,从而最终能帮助我们解决实际的问题。

下面是利用Prompt Creator生成提示词的实例:

作为用户,您的目标是为 ChatGPT 创建最佳提示以满足您的特定需求。您提供的提示应该从您的角度编写,请求 ChatGPT 帮助制作理想的提示。请记住,此提示将被输入到 ChatGPT 的界面中。按照下面概述的过程创建提示:


提示:

{请提供尽可能好的提示,准确传达您的要求和要求。在提示中要清晰、具体、简洁。


批判:

{请简明扼要地说明如何改进提示。在回答中要有批判性,并提供改进建议。


问题:

{最多提出三个问题,以澄清任何需要更多信息的领域,或收集更多细节以增强提示。


在我们的迭代过程中,您将为我的回复提供您的答案,我将使用相同的格式将它们合并到我的下一个回复中。我们将继续这个过程,直到提示完善为止。记住要仔细思考,用你的想象力创造一个惊人的提示,有效地将你的需求传达给ChatGPT。


对于您的第一个响应,请向用户打招呼,并询问他们提示的内容。

上面这个prompt的作用是让chatgpt按步骤完成以下任务:首先让chatgpt根据用户描述生成一个初步的prompt;然后让chatgpt对自己生成的prompt进行评价和可以改进的方面;接着chatgpt向用户提问题,获得更多相关知识来改善prompt。用户可以根据chatpt提出的改进方面来补充相关知识。因为一开始用户可能不知道需要添加什么信息,通过让chatgpt自己提问和需要改进的方面来启发用户来添加重要信息从而完善prompt;然后用户根据需要选择回答对应的问题,让chatpgt根据用户的回答再生成一个改进之后的prompt。不断往复这样的流程,通过问答的方式一步步启发用户完善信息,优化提示词,最终完成prompt的生成。

03 使用chatgpt写周定投程序

我们将上述Prompt Creator技术应用到广告数据源理解项目(给广告文案数据打标)和落地页生成项目(这里会涉及生成广告标题、正文、头图提示词等)中,因为某些原因后续会分享相关的文章。刚好最近大A刚打响了3000点保卫战,作为理财小白的我也学习了很多基金定投的知识,所以想趁着这个机会用chatgpt来帮我们写一个基金定投的程序,来看下通过基金定投的方式我们普通小散到底能不能赚到钱。

关于基金定投的理论知识主要是学习喜马拉雅里主播《威尼斯摆渡人》的专辑《每天五分钟,基金定投聊通透》。这个主播已经更新了很多年了,关于基金定投的知识讲的也非常全面,收益良多。本篇重点介绍使用chatgpt帮我们写周定投的程序,同时帮我验证下到底普通人通过基金定投能不能赚到钱,关于基金定投知识的细节小伙伴们自行学习。基金定投中一个非常重要的因素是选对基金,本篇选择的是我非常欣赏的一个基金经理朱少醒的富国天惠成长混合(LOF)A(161005)。这两个大V有个共同的点我很喜欢,就是可以长时间坚持做一件事。

3.1 获取基金数据

可以在网站《英为财情》上下载相关的基金历史数据,网址如下:

https://cn.investing.com/funds/fullgoal-tianhui-selected-growth-mi-historical-data

下载数据方式如下

广告行业中那些趣事系列65:使用chatgpt编写基金定投程序_ci_02


图1 《英为财情》下载基金历史数据

将下载到的基金数据进行预处理得到161005.txt文件,只保留两列数据,第一列是日期数据,第二列是基金当天的净值数据。

3.2 设计prompt得到程序示例

定投基金的思想其实很简单,以周定投为例,就是每周四(其他工作日也可以)买入一定金额的基金即可。同时设置一个赎回策略,比如达到一定的年化收益率之后就把基金全部卖出,完成此轮定投。然后开始下一轮的定投,周而复始。我们希望根据历史基金数据来验证周定投到底能不能赚到钱,输入是三个参数:开始定投基金的日期、结束定投基金的日期和目标年化收益率;输出是这段时间基金定投的收益情况,会输出每一轮定投基金买卖的开始日期、卖出日期、投入的本金总额、卖出基金获得的总金额以及年化收益率。比如我们设置2020.1.1到开始到2023.1.1结束,这段时间每周四会买入1000块的基金,如果年化收益率达到20%则进行赎回,开启下一轮定投。这里我们设计的prompt如下:

Prompt = """
使用python标准库写一个可执行的周定投的量化程序,输入是一个161005.txt文件,有两列数据,通过\t分隔。第一列是日期,第二列是基金当天的收盘数据,代表基金当天的价格,数据示例如下所示:
2010年1月4日 1.635
2010年1月5日 1.649
 
请一步步编写程序:
首先设置一个初始日期、结束日期和年化收益率;
然后从初始日期开始进行第一轮的基金定投:往后有收盘数据的每一天如果小于结束日期,先判断是否是周四,如果是周四则买入1000块的基金。同时判断有收盘数据的每一天当前持有基金的年化收益率,如果年化收益率大于20%,则第一轮基金定投结束,卖出当前这一轮持有的全部基金,并输出结果,输出的结果是一个列表,列表中有五个元素,分别是当前这一轮基金买卖的开始日期、卖出日期、投入的本金总额、卖出基金获得的总金额以及年化收益率。卖出基金之后的第二天开始下一轮基金定投,同样满足年化收益则输出第二轮的列表数据,直到结束日期,不断循环往复。如果一直到结束日期均没有达到年化收益率,则输出新的一轮基金定投的开始日期,结束日期,投入的本金总额,持有基金的总金额以及年化收益率。
 
需要注意以下几点规则:
1根据日期识别当天是否是星期四,如果是星期四并且当天有收盘数据,则买入1000块的基金,如果是星期四但没有收盘数据,那么下一个有收盘数据的日期买入1000块的基金;
2如果从开始日期和结束日期这段时间内都没有达到止盈目标,那么返回列表,列表中有五个元素,分别是开始日期、结束日期、投入的本金总额、基金当前的总金额以及当前的年化收益率;
3需要注意程序中如果存在除法计算,那么分母不能为零;
4如果有一轮基金定投总共投入了10000元,满足年化收益率20%的时候中间刚好经历了两年,那么只有当前持有的基金总额超过140000元时则进行卖出。
 
举例说明:
示例:如果我们输入开始日期是2010年1月5日,结束日期是2015年1月5日,年化收益率是20%,假如我们总共投入10000元,那么因为中间有五年,按照年化收益率20%来算,我们需要金额达到20000时进行赎回,如果一直到2015年1月5日之前都没有达到基金卖出的条件,并且在2015年1月5日当天我们年化收益率达到了20%,那么我们执行卖出操作。
输入:
start_date = datetime.strptime('2010年1月5日', '%Y年%m月%d日')
end_date = datetime.strptime('2015年1月5日', '%Y年%m月%d日')
annua_return_rate = 20
输出:[[‘2010年1月5日’, ‘2015年1月5日’, ‘10000’, ‘20000’, ‘20%’]]
"""

使用chatgpt根据prompt生成python程序代码如下所示:

import datetime

def calculate_annualized_return(investment, end_value, start_date, end_date):
    #print(investment, end_value, start_date, end_date)
    if end_date == start_date:
        return 0
    
    duration = (end_date - start_date).days
    if investment>0 and duration>0:
        #annualized_return = ((end_value / investment) ** (duration / 365) - 1) * 100
        annualized_return = ((end_value-investment) / investment)*365/duration
        annualized_return = round(annualized_return, 2)
        return annualized_return
    else:
        return 0 

def find_next_thursday(date):
    while date.weekday() != 3:  # 3 represents Thursday
        date += datetime.timedelta(days=1)
    return date

def find_invalidate_start_date(start_date, date_list):
    for date, close_price in date_list:
        if start_date==date:
            return start_date
        else:
            if date>start_date:
                return date 

def process_investment(file_path, start_date, end_date, annualized_return_threshold):
    # Read data from file
    data = []
    with open(file_path, 'r') as file:
        next(file)  # skip the header
        for line in file:
            date, close_price = line.strip().split('\t')
            close_price = float(close_price)
            data.append((datetime.datetime.strptime(date, '%Y年%m月%d日'), close_price))

    # Initialize variables
    #investment_start_date = start_date
    investment_start_date = find_invalidate_start_date(start_date, data)
    investment_end_date = None
    investment_principal = 0
    holding_value = 0
    result = []
    
    # Process each data point
    for date, close_price in data:
        if date < start_date:
            continue
        if date > end_date:
            break
            
        # Check if it's Thursday and buy fund
        if date.weekday() == 3:
            investment_principal += 1000
            holding_value += 1000 / close_price

        # Check the current holding's annualized return
        investment_end_date = date
        annualized_return = calculate_annualized_return(investment_principal, holding_value * close_price,
                                                       investment_start_date, investment_end_date)
        
        #if date.weekday() == 3:
        #   print(investment_principal, holding_value * close_price,
        #                                              investment_start_date, investment_end_date, annualized_return)
        
        # Check if the current holding exceeds the threshold
        if (annualized_return >= annualized_return_threshold) and (((investment_end_date - investment_start_date).days)>180):
            result.append((investment_start_date, investment_end_date, investment_principal,
                           round(holding_value * close_price), annualized_return))
            
            # Sell all the fund
            holding_value = 0
            investment_principal = 0
            investment_start_date = investment_end_date + datetime.timedelta(days=1)
            investment_start_date = find_invalidate_start_date(investment_start_date, data)
    
    #print(investment_principal, holding_value * close_price,
    #                                                   investment_start_date, investment_end_date, annualized_return)
    # Calculate the last holding's annualized return
    final_annualized_return = calculate_annualized_return(investment_principal, holding_value * close_price,
                                                          investment_start_date, investment_end_date)
    
    result.append((investment_start_date, investment_end_date, investment_principal,
                   round(holding_value * close_price), final_annualized_return))
    
    return result

# Example usage
file_path = '161005.txt'
start_date = datetime.datetime(2010, 1, 1)
end_date = datetime.datetime(2023, 9, 1)
annualized_return_threshold = 0.22

result = process_investment(file_path, start_date, end_date, annualized_return_threshold)

# 增加每次赎回时当前赚取收益,累计收益
cumulative_income = 0
for r in result:
    perioded_income = r[3]-r[2]
    cumulative_income += perioded_income
    print(r, round(perioded_income), round(cumulative_income))

在实际生成过程中,可能会有些小bug,这里解决下就好。这里程序还需要进行优化,比如没有计算基金买入和卖出的手续费用功能等。

04 周定投大A是不是真的能赚钱

使用chatgpt完成周定投程序之后我们来验证下到底周定投大A是不是真能赚到钱。

4.1 设置止盈策略的重要性

在基金定投中赚钱的一个非常重要的因素是是否设置止盈策略。止盈就是基金定投过程中卖出的策略。下图是我们从2020.1.1号开始到2023.9.1这段时间每周四定投基金1000块一直买入基金,不进行卖出操作下本金投入情况(蓝色曲线)、基金价值(红色曲线)总额和年化收益率(绿色柱状图)情况:

广告行业中那些趣事系列65:使用chatgpt编写基金定投程序_ci_03


图2 基金不设置止盈的投入和收益情况

上图中对年化收益率进行了特殊处理,因为前期如果基金出现亏损,同时时间很短,很容易导致年化收益率值特别低,达到负100%以上,导致我们整体的年化率收益图不美观。这里将年化收益率的最低值设置为-50%,只要超过这个最低值则直接为-50%。

从上图中可以看出,如果我们不止盈,很容易出现“曾经赚过很多钱”的情况。比如2015年出现牛市,年化收益率可以达到20%以上。但是这波如果没有止盈的话,到2016年赚的又全部亏回去了,甚至到2019年还会出现亏损的情况。这是非常难易接受的。选择合适的止盈策略非常重要,这里重点是到底设置年化收益率多少为我们的止盈点。咱们大A是典型的“牛短熊长”,如果年化收益率设置的太低,可能牛市刚开启我们就把好不容易在长期熊市中积累的筹码卖出去了;如果年化收益率设置的太高,可能导致没有到达止盈点从而错过卖出的好机会,导致错过一轮好的行情。

4.2 设置不同年化率的影响

下表是使用周定投策略,从2020.1.1号开始到2023.9.1这段时间每周四定投基金1000块,分别设置10%-29%的投资收益情况。

广告行业中那些趣事系列65:使用chatgpt编写基金定投程序_数据_04


图3 设置不同年化率的影响

可以发现年化收益率从10%到21%是投资收益是不断提升的,从125400一直增加到490043。这里需要注意10%以下的投资收益情况是低于10%的收益的,所以这里直接忽略。可以看出当采用周定投策略时当设置的年化收益率过低时,投资收益也是比较低的。需要注意的是当收益率超过21%时投资收益会出现一个明显的下跌,从490043下降到308364。这里详细分析下原因。因为上面是开始定投基金和结束定投基金这段时间的累计收益,中间可能有好几次触发了止盈策略,所以我们把每一轮触发定投止盈的数据打印出来。下面是分别设置年化收益率0.2、0.21和0.22下每轮定投开始时间、结束时间、投资本金、基金价值总额、年化收益率、当前这一轮基金投资收益和累计收益。举例说明,当我们设置年化收益率为20%时,从2010.1.5-2023.9.1这段时间一共进行了5轮基金定投,第一轮是从2010.1.5-2010.1020,经历将近10个多月时间,投入本金38000,基金总价值44120,本轮基金定投赚取6120,因为是第一轮定投所以累收益也是6120;然后开始第二轮基金投资,从2010.10.21-2015.5.12,经历将近4年半的时间,投入本金224000,基金总价值428252,本轮基金定投赚取204252,加上上一轮基金收益一共累计赚取210372。然后是第三轮2015.5.13-2015.12.22和第四轮2015.12.23-2021.2.9,都满足了年化20%的止盈线并进行了止盈策略。需要注意的是最后一轮,这一轮是从2021.2.10-2023.9.1,投入本金134000,基金总价值118221,是亏损的,收益率为-5%,本轮定投亏损15779。也就是说从2021.2.10-2023.9.1行情非常差,处于亏损状态。下面是详细数据:

0.2
((2010, 1, 5), (2010, 10, 20), 38000, 44120, 0.2) 6120 6120
((2010, 10, 21), (2015, 5, 12), 224000, 428252, 0.2) 204252 210372
((2015, 5, 13), (2015, 12, 22), 32000, 35877, 0.2) 3877 214249
((2015, 12, 23), (2021, 2, 9), 268000, 540636, 0.2) 272636 486885
((2021, 2, 10), (2023, 9, 1), 134000, 118221, -0.05) -15779 471106
 
0.21
((2010, 1, 5), (2010, 10, 25), 39000, 45838, 0.22) 6838 6838
((2010, 10, 26), (2015, 5, 18), 224000, 434071, 0.21) 210071 216909
((2015, 5, 19), (2015, 12, 22), 31000, 34881, 0.21) 3881 220790
((2015, 12, 23), (2021, 2, 10), 268000, 553032, 0.21) 285032 505822
((2021, 2, 11), (2023, 9, 1), 134000, 118221, -0.05) -15779 490043
 
0.22
((2010, 1, 5), (2010, 10, 25), 39000, 45838, 0.22) 6838 6838
((2010, 10, 26), (2015, 5, 20), 224000, 453851, 0.22) 229851 236689
((2015, 5, 21), (2023, 9, 1), 433000, 504675, 0.02) 71675 308364

对上面数据进行分析,我们可以发现年化收益率22%相比于21%收益下降了非常多,一个主要原因是2015.5.21-2023.9.1没有触发止盈策略,导致出现了“曾经赚过很多钱”的情况。从这个数据中我们可以得到以下几个有价值的结论:

(1)周定投富国天惠这支基金的确是可以赚钱的。针对咱们大A是一个“牛短熊长”的股市,由于我们无法预知未来股市的情况,所以可以通过定投的方式在长期的熊市中积累筹码,然后等市场发动大级别的行情时可以获得对应的收益;

(2)设置合适的止盈年化收益率非常重要。如果设置的年化收益率过低,会导致好不容易在漫漫熊市中积累的筹码在稍微上涨一点就卖出了,少赚就是亏;如果设置的年化收益率过高,又会出现长期无法止盈的情况,导致错过一段或者多段收益。所以设置合适的止盈年化收益可以让我们最大长度赚钱定投基金的收益;

(3)从2021.2.11到现在这段时间,定投将近两年半的时间,收益率是-5%。可以看出这是一段熊市行情,处于相对底部的区间,可以把握机会,慢慢定投,等待下一波的行情。

通过图表的方式查看设置年化收益率为21%和22%的定投收益差异:

广告行业中那些趣事系列65:使用chatgpt编写基金定投程序_ci_05


图4 设置年化收益率为21%和22%的定投收益差异

从上图中可以看出,在2021.1.7日附近当我们设置年化收益率为21%(蓝线所示)时达到止盈策略对基金进行卖出顺利的锁定了这一轮基金定投的利润。而后面就是一轮惨烈的暴跌,而设置年化收益率为22%(橘黄色线)时因为没有达到止盈线从而没有进行赎回操作,导致从2015年1月积累的利润疯狂回吐。

4.3 周几对周定投的影响

上面我们是选择在周四进行定投操作,可能有小伙伴问为啥要选择周四进行定投呢?这里我们对比下设置年化收益率为21%时分别在周一到周五进行定投时投资总收益情况:

广告行业中那些趣事系列65:使用chatgpt编写基金定投程序_数据_06


图5 周几对周定投的影响

从上图中可以发现,选择周几定投对整体定投收益影响不大,但是最适合定投的工作日是周三,最不适合定投的工作日是周一,整体来看收益率相差3.5%。

总结和反思

本篇介绍了prompt生成器和使用chatgpt来编写一个基金定投程序。首先是背景介绍,我们在日常工作和生活中可以使用chatgpt来大大提升工作效率;然后介绍了prompt生成器的原理以及使用示例;接着重点介绍了使用chatgpt来帮助我们编写一个基金周定投程序,包括基金数据获取和设计prompt得到程序示例;最后通过数据分析验证普通散户通过合适的周定投策略的确可以在大A赚取到丰厚的收益,重点分析了止盈策略的重要性、设置不同年化率的影响以及周几对周定投的影响。对于希望使用chatgpt提升工作效率,尤其是对投资基金感兴趣的小伙伴可能有帮助

最新最全的文章请关注我的微信公众:数据拾光者。

码字不易,欢迎小伙伴们点赞和分享。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月01日 0

暂无评论

推荐阅读
dqHClNfrJu09