超级安全!Python Pillow合成多张图片到PDF格式

在日常生活中,经常会遇到需要提交身份证正反面证明资料的情况,而且这些网站大部分只接受pdf格式,这时候我们就需要把身份证正反面两张图片合成为一个pdf文件。

在macOS系统下,预览软件可以轻松做到这一点,同时打开图片到一个预览窗口下,点击导出PDF就能成功导出。但是Windows系统就没有这么方便的软件可以实现这一点,网上有很多合成PDF的网站,但是这些网站无一例外需要上传PDF进行合成,个人认为非常地不安全。

因此,最安全的方法,还是我们自己写一个Python脚本实现合成功能。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pillow

2.Pillow 合成PDF原理

Pillow模块,即PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。通过它,我们能很轻松地操作图像,并导出为不同格式。

首先来一个简单的示例,我们将打开一张图片,并将其保存为pdf格式:

from PIL import Image
import os


def convert_img_pdf(filepath, output_path):
    """
    转换图片为pdf格式

    Args:
        filepath (str): 文件路径
        output_path (str): 输出路径
    """
    output = Image.open(filepath)
    output.save(output_path, "pdf", save_all=True)
    
    
if __name__ == "__main__":
    convert_img_pdf("1.jpeg", "./test.pdf")

随便使用一张图片测试一下:

在运行代码后,它便成功地转化为了PDF文件:

几行代码便完成了这个转换,这个可比那些把照片上传到云端的网站安全多了。

3.多张照片合成PDF

有了前面照片转化PDF的基础知识,想要理解下面的多图合成PDF的代码就非常简单了。

其实就是使用了.save的一个特殊参数 append_images:

output.save(pdfFilePath, "pdf", save_all=True, append_images=sources)

通过把图片都存入到一个”sources”数组中,我们就能很轻易地合成这些图像到PDF中。

from PIL import Image
import os

def combine_imgs_pdf(folder_path, pdf_file_path):
    """
    合成文件夹下的所有图片为pdf

    Args:
        folder_path (str): 源文件夹
        pdf_file_path (str): 输出路径
    """
    files = os.listdir(folder_path)
    png_files = []
    sources = []
    for file in files:
        if 'png' in file or 'jpg' in file:
            png_files.append(folder_path + file)
    png_files.sort()

    output = Image.open(png_files[0])
    png_files.pop(0)
    for file in png_files:
        png_file = Image.open(file)
        if png_file.mode == "RGB":
            png_file = png_file.convert("RGB")
        sources.append(png_file)
    output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)

if __name__ == "__main__":
    folder = r"G:\证件\\"
    pdfFile = r"G:\证件\身份证.pdf"
    combine_imgs_pdf(folder, pdfFile)

这样,只要将你的证件照都放在一个文件夹中,运行这个Python代码,它就能自动将这些证件合成到一个PDF中,并输出到你指定的路径。非常简单方便。

有需要的小伙伴,刚开那这份代码去试一下吧!在Python实用宝典后台回复 合成pdf 就能下载啦!

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python超好用的命令行参数工具—Click

Click 是一个简洁好用的Python模块,它能用尽量少的代码实现漂亮的命令行界面。它不仅开箱即用、还能支持高度自定义的配置。

一个简单的示例如下:

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

效果如下:

可见这个模块的强大之处,你只需要在对应的函数上加几个装饰器,就能实现带提示符的命令行界面的创建,相当方便。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install click

2.基本使用

如文首所示的例子一样,@click.option 是最基本的选项,它既可以设定参数默认值,也可以设定必须传入参数:

@click.command()
@click.option('--n', default=1) # 设定了默认值
def dots(n):
    click.echo('.' * n)
    

@click.command()
@click.option('--n', required=True, type=int) # 设定必须传入参数值
def dots(n):
    click.echo('.' * n)

如果你设置了必须传入相关参数,那么在没传入参数的情况下,效果是这样的:

当然,它还支持设定多种参数别名,比如下面的 –from 和 -f 是等效的:

@click.command()
@click.option('--from', '-f', 'from_')
@click.option('--to', '-t')
def reserved_param_name(from_, to):
    click.echo(f"from {from_} to {to}")

3.多值参数

如果你的选项需要多个参数,Click也能帮你实现这个需求。

@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
    a, b = pos
    click.echo(f"{a} / {b}")

可见,通过配置nargs参数,你可以将用户传递的值存入元组,并在代码中解包这个元组拿到所有的值。

效果如下:

你还可以配置一个参数叫 multiple,这个参数可以让你接受N个值:

@click.command()
@click.option('--message', '-m', multiple=True)
def commit(message):
    click.echo(' '.join(message))

效果如下:

4.其他功能

你还可以使用Click来计数,这个使用非常罕见:

@click.command()
@click.option('-v', '--verbose', count=True)
def log(verbose):
    click.echo(f"Verbosity: {verbose}")

效果如下:

布尔标志

此外,Click还带有布尔标志功能,你可以直接使用 “/” 来标志参数为二选一参数,函数中直接就会拿到布尔型的变量:

import sys

@click.command()
@click.option('--shout/--no-shout', default=False)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

效果如下:

选择选项

你可以直接限定用户的输入范围:

@click.command()
@click.option('--hash-type',
              type=click.Choice(['MD5', 'SHA1'], case_sensitive=False))
def digest(hash_type):
    click.echo(hash_type)

提示文本

在文首提到的例子中,输出了个 “You name:” 的提示,其实是 option 中的prompt参数控制的:

@click.command()
@click.option('--name', prompt='Your name please')
def hello(name):
    click.echo(f"Hello {name}!")

好了,Click的功能就介绍到这里,他还有许多高级的用法,比如动态默认值、回调函数等等,大家可以通过官方文档了解这些高级功能的使用方法:

https://click.palletsprojects.com/en/8.0.x/options/#name-your-options

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

FreqTrade—又强又简单的Python加密货币自动交易机器人

Freqtrade 是一个用 Python 编写的免费开源加密货币交易机器人。它旨在支持所有主要交易所并通过 Telegram 或 webUI 进行控制。功能包含回测、绘图和资金管理工具以及通过机器学习的策略优化。

目前支持的交易所:

特性:

  •  基于 Python 3.8+:适用于任何操作系统 – Windows、macOS 和 Linux。
  •  持久性:持久性是通过 sqlite 实现的。
  •  Dry-run:不花钱运行机器人。
  •  回测:模拟买入/卖出策略。
  •  通过机器学习进行策略优化:使用机器学习通过真实的交易所数据优化买入/卖出策略参数。
  •  边缘头寸规模计算您的胜率、风险回报率、最佳止损位并在为每个特定市场建立头寸之前调整头寸规模。
  •  白名单加密货币:选择你要交易的加密货币或使用动态白名单。
  •  黑名单加密货币:选择你想要避免的加密货币。
  •  内置 WebUI:内置 Web UI 来管理你的机器人。
  •  可通过 Telegram管理:使用 Telegram 管理机器人。
  •  以法定货币显示盈亏:以法定货币显示你的盈亏。
  •  表现状态报告:提供你当前交易的表现状态。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

在Linux/MacOS下,三行命令就能完成安装:

git clone -b develop https://github.com/freqtrade/freqtrade.git
cd freqtrade
./setup.sh --install

如果你无法克隆此项目,请在Python实用宝典公众号后台回复:freqtrade 下载。

Windows环境下打开Cmd(开始—运行—CMD),输入命令安装依赖:

git clone https://github.com/freqtrade/freqtrade.git
cd freqtrade
# 安装ta-lib
pip install build_helpers/TA_Lib-0.4.24-cp38-cp38-win_amd64.whl
pip install -r requirements.txt
pip install -e .
freqtrade

请注意,此处安装ta-lib时项目方提供了python3.8/3.9/3.10,其他Python版本请自行搜索下载。

输入freqtrade时,显示以下信息说明安装成功:

(freqtrade) D:\CODE\trader\freqtrade>freqtrade
2022-02-17 19:40:50,174 - freqtrade - ERROR - Usage of Freqtrade requires a subcommand to be specified.
To have the bot executing trades in live/dry-run modes, depending on the value of the `dry_run` setting in the config, run Freqtrade as `freqtrade trade [options...]`.
To see the full list of options available, please use `freqtrade --help` or `freqtrade <command> --help`.

2.Freqtrade 快速开始

下面教你如何开发一个简单的交易策略。

一个策略文件往往包含这些东西:

  • 指标
  • 购买规则
  • 卖出规则
  • 建议最低投资回报率
  • 强烈推荐止损

Freqtrade使用 Pandas 作为基础数据结构,它底层的OHLCV都是以Dataframe的格式存储的。

Dataframe数据流中每一行数据代表图表上的一根K线,最新的K线始终是数据库中最后一根。

> dataframe.head()
                       date      open      high       low     close     volume
0 2021-11-09 23:25:00+00:00  67279.67  67321.84  67255.01  67300.97   44.62253
1 2021-11-09 23:30:00+00:00  67300.97  67301.34  67183.03  67187.01   61.38076
2 2021-11-09 23:35:00+00:00  67187.02  67187.02  67031.93  67123.81  113.42728
3 2021-11-09 23:40:00+00:00  67123.80  67222.40  67080.33  67160.48   78.96008
4 2021-11-09 23:45:00+00:00  67160.48  67160.48  66901.26  66943.37  111.39292

Pandas 提供了计算指标的快速方法。为了从这种速度中受益,建议不要使用循环,而是使用矢量化方法。

矢量化操作在整个数据范围内执行计算,因此,与遍历每一行相比,在计算指标时要快得多。

dataframe.loc[(dataframe['rsi'] > 30), 'buy'] = 1

类似于上面这样的赋值方法,会自动设置rsi大于30的数据的buy列的值为1。

买入规则

def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    """
    Based on TA indicators, populates the buy signal for the given dataframe
    :param dataframe: DataFrame populated with indicators
    :param metadata: Additional information, like the currently traded pair
    :return: DataFrame with buy column
    """
    dataframe.loc[
        (
            (qtpylib.crossed_above(dataframe['rsi'], 30)) &  # Signal: RSI crosses above 30
            (dataframe['tema'] <= dataframe['bb_middleband']) &  # Guard
            (dataframe['tema'] > dataframe['tema'].shift(1)) &  # Guard
            (dataframe['volume'] > 0)  # Make sure Volume is not 0
        ),
        'buy'] = 1

    return dataframe

请注意,一定要不修改并返回”open”, “high”, “low”, “close”, “volume”列,这些是基础行情数据,如果返回错误的数据将可能会导致一些奇怪数据的产生。

如上所示的方法中,符合条件的数据的buy值会被设为1代表买入,否则为0或nan值。

卖出规则

def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    """
    Based on TA indicators, populates the sell signal for the given dataframe
    :param dataframe: DataFrame populated with indicators
    :param metadata: Additional information, like the currently traded pair
    :return: DataFrame with buy column
    """
    dataframe.loc[
        (
            (qtpylib.crossed_above(dataframe['rsi'], 70)) &  # Signal: RSI crosses above 70
            (dataframe['tema'] > dataframe['bb_middleband']) &  # Guard
            (dataframe['tema'] < dataframe['tema'].shift(1)) &  # Guard
            (dataframe['volume'] > 0)  # Make sure Volume is not 0
        ),
        'sell'] = 1
    return dataframe

与买入类似,这里不赘述了。

最小投资回报率

在类中增加这个初始化变量,能控制投资回报率:

minimal_roi = {
    "40": 0.0,
    "30": 0.01,
    "20": 0.02,
    "0": 0.04
}

上述配置意味着:

  • 只要达到 4% 的利润就卖出
  • 达到 2% 利润时卖出(20 分钟后生效)
  • 达到 1% 利润时卖出(30 分钟后生效)
  • 交易未亏损时卖出(40 分钟后生效)

此处的计算包含费用。

要完全禁用 ROI,请将其设置为一个非常高的数字:

minimal_roi = {
    "0": 100
}

虽然从技术上讲并没有完全禁用,但一旦交易达到 10000% 利润,它就会卖出。

止损

强烈建议设置止损,以保护资金免受不利的剧烈波动。

设置 10% 止损的示例:

stoploss = -0.10

一个完整代码如下:

# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these libs ---
from re import A
import numpy as np  # noqa
import pandas as pd  # noqa
from pandas import DataFrame

from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
                                IStrategy, IntParameter)

# --------------------------------
# 你自己所需要的模块放在这里
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib


# This class is a sample. Feel free to customize it.
class SampleStrategy(IStrategy):
    """
    This is a sample strategy to inspire you.
    More information in https://www.freqtrade.io/en/latest/strategy-customization/
    You can:
        :return: a Dataframe with all mandatory indicators for the strategies
    - Rename the class name (Do not forget to update class_name)
    - Add any methods you want to build your strategy
    - Add any lib you need to build your strategy
    You must keep:
    - the lib in the section "Do not remove these libs"
    - the methods: populate_indicators, populate_buy_trend, populate_sell_trend
    You should keep:
    - timeframe, minimal_roi, stoploss, trailing_*
    """
    # Strategy interface version - allow new iterations of the strategy interface.
    # Check the documentation or the Sample strategy to get the latest version.
    INTERFACE_VERSION = 2

    # 设定最小投资回报
    minimal_roi = {
        "60": 0.01,
        "30": 0.02,
        "0": 0.04
    }

    # 止损
    stoploss = -0.10

    # 指标参数
    buy_rsi = IntParameter(low=1, high=50, default=30, space='buy', optimize=True, load=True)
    sell_rsi = IntParameter(low=50, high=100, default=70, space='sell', optimize=True, load=True)

    # K线时间
    timeframe = '5m'

    # 在新K线出现时执行
    process_only_new_candles = False

    # These values can be overridden in the "ask_strategy" section in the config.
    use_sell_signal = True
    sell_profit_only = False
    ignore_roi_if_buy_signal = False

    # 预准备K线数
    startup_candle_count: int = 30

    # 下单类型
    order_types = {
        'buy': 'limit',
        'sell': 'limit',
        'stoploss': 'market',
        'stoploss_on_exchange': False
    }

    # 订单有效时间(gtc: 除非取消否则一直有效)
    order_time_in_force = {
        'buy': 'gtc',
        'sell': 'gtc'
    }

    plot_config = {
        'main_plot': {
            'tema': {},
            'sar': {'color': 'white'},
        },
        'subplots': {
            "MACD": {
                'macd': {'color': 'blue'},
                'macdsignal': {'color': 'orange'},
            },
            "RSI": {
                'rsi': {'color': 'red'},
            }
        }
    }

    def informative_pairs(self):
        """
        Define additional, informative pair/interval combinations to be cached from the exchange.
        These pair/interval combinations are non-tradeable, unless they are part
        of the whitelist as well.
        For more information, please consult the documentation
        :return: List of tuples in the format (pair, interval)
            Sample: return [("ETH/USDT", "5m"),
                            ("BTC/USDT", "15m"),
                            ]
        """
        return []

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Adds several different TA indicators to the given DataFrame
        Performance Note: For the best performance be frugal on the number of indicators
        you are using. Let uncomment only the indicator you are using in your strategies
        or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
        :param dataframe: Dataframe with data from the exchange
        :param metadata: Additional information, like the currently traded pair
        :return: a Dataframe with all mandatory indicators for the strategies
        """

        # Momentum Indicators
        # ------------------------------------

        dataframe['adx'] = ta.ADX(dataframe)
        dataframe['rsi'] = ta.RSI(dataframe)
        stoch_fast = ta.STOCHF(dataframe)
        dataframe['fastd'] = stoch_fast['fastd']
        dataframe['fastk'] = stoch_fast['fastk']

        # MACD
        macd = ta.MACD(dataframe)
        dataframe['macd'] = macd['macd']
        dataframe['macdsignal'] = macd['macdsignal']
        dataframe['macdhist'] = macd['macdhist']

        # MFI
        dataframe['mfi'] = ta.MFI(dataframe)

        # Bollinger Bands
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        dataframe["bb_percent"] = (
            (dataframe["close"] - dataframe["bb_lowerband"]) /
            (dataframe["bb_upperband"] - dataframe["bb_lowerband"])
        )
        dataframe["bb_width"] = (
            (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
        )

        # Parabolic SAR
        dataframe['sar'] = ta.SAR(dataframe)

        # TEMA - Triple Exponential Moving Average
        dataframe['tema'] = ta.TEMA(dataframe, timeperiod=9)

        hilbert = ta.HT_SINE(dataframe)
        dataframe['htsine'] = hilbert['sine']
        dataframe['htleadsine'] = hilbert['leadsine']

        return dataframe

    def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the buy signal for the given dataframe
        :param dataframe: DataFrame populated with indicators
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with buy column
        """
        dataframe.loc[
            (
                # Signal: RSI crosses above 30
                (qtpylib.crossed_above(dataframe['rsi'], self.buy_rsi.value)) &
                (dataframe['tema'] <= dataframe['bb_middleband']) &  # Guard: tema below BB middle
                (dataframe['tema'] > dataframe['tema'].shift(1)) &  # Guard: tema is raising
                (dataframe['volume'] > 0)  # Make sure Volume is not 0
            ), 'buy'] = 1

        return dataframe

    def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Based on TA indicators, populates the sell signal for the given dataframe
        :param dataframe: DataFrame populated with indicators
        :param metadata: Additional information, like the currently traded pair
        :return: DataFrame with sell column
        """
        dataframe.loc[
            (
                # Signal: RSI crosses above 70
                (qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value)) &
                (dataframe['tema'] > dataframe['bb_middleband']) &  # Guard: tema above BB middle
                (dataframe['tema'] < dataframe['tema'].shift(1)) &  # Guard: tema is falling
                (dataframe['volume'] > 0)  # Make sure Volume is not 0
            ), 'sell'] = 1
        return dataframe
        

3.启动机器人

启动机器人前还需要设定配置,配置模板在 config/examples 下面。

比如币安的配置,你还需要输入key和secret:

"exchange": {
        "name": "binance",
        "key": "your_exchange_key",
        "secret": "your_exchange_secret",
  	    ......
	}
}

启动机器人:

freqtrade trade --strategy AwesomeStrategy --strategy-path /some/directory  -c path/far/far/away/config.json

–strategy-path 指定策略文件位置

-c 参数指定配置文件位置

比如我把策略放在了user_data/strategies下,配置放在了config_examples下,这么输入命令启动机器人即可:

freqtrade trade --strategy SampleStrategy --strategy-path user_data/strategies  -c config_examples/config_binance.example.json

由于篇幅问题,本文只是介绍了freqtrade的冰山一角,在启动机器人前,一定要进行回测并进行模拟交易。它还有TG通知功能、WebUI管理界面,详细的使用方法大家可以参考官方教程:

https://www.freqtrade.io/en/stable/

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

为什么说Python大数据处理一定要用Numpy Array?

Numpy 是Python科学计算的一个核心模块。它提供了非常高效的数组对象,以及用于处理这些数组对象的工具。一个Numpy数组由许多值组成,所有值的类型是相同的。

Python的核心库提供了 List 列表。列表是最常见的Python数据类型之一,它可以调整大小并且包含不同类型的元素,非常方便。

那么List和Numpy Array到底有什么区别?为什么我们需要在大数据处理的时候使用Numpy Array?答案是性能。

Numpy数据结构在以下方面表现更好:

1.内存大小—Numpy数据结构占用的内存更小。

2.性能—Numpy底层是用C语言实现的,比列表更快。

3.运算方法—内置优化了代数运算等方法。

下面分别讲解在大数据处理时,Numpy数组相对于List的优势。

1.Numpy Array内存占用更小

适当地使用Numpy数组替代List,你能让你的内存占用降低20倍。

对于Python原生的List列表,由于每次新增对象,都需要8个字节来引用新对象,新的对象本身占28个字节(以整数为例)。所以,列表 list 的大小可以用以下公式计算:

64 + 8 * len(lst) + len(lst) * 28 字节

而使用Numpy,就能减少非常多的空间占用。比如长度为n的Numpy整形Array,它需要:

96 + len(a) * 8 字节

可见,数组越大,你节省的内存空间越多。假设你的数组有10亿个元素,那么这个内存占用大小的差距会是GB级别的。

2.Numpy Array速度更快、内置计算方法

运行下面这个脚本,同样是生成某个维度的两个数组并相加,你就能看到原生List和Numpy Array的性能差距。

import time
import numpy as np

size_of_vec = 1000

def pure_python_version():
    t1 = time.time()
    X = range(size_of_vec)
    Y = range(size_of_vec)
    Z = [X[i] + Y[i] for i in range(len(X)) ]
    return time.time() - t1

def numpy_version():
    t1 = time.time()
    X = np.arange(size_of_vec)
    Y = np.arange(size_of_vec)
    Z = X + Y
    return time.time() - t1


t1 = pure_python_version()
t2 = numpy_version()
print(t1, t2)
print("Numpy is in this example " + str(t1/t2) + " faster!")

结果如下:

0.00048732757568359375 0.0002491474151611328
Numpy is in this example 1.955980861244019 faster!

可以看到,Numpy比原生数组快1.95倍。

如果你细心的话,还能发现,Numpy array可以直接执行加法操作。而原生的数组是做不到这点的,这就是Numpy 运算方法的优势。

我们再做几次重复试验,以证明这个性能优势是持久性的。

import numpy as np
from timeit import Timer

size_of_vec = 1000
X_list = range(size_of_vec)
Y_list = range(size_of_vec)
X = np.arange(size_of_vec)
Y = np.arange(size_of_vec)

def pure_python_version():
    Z = [X_list[i] + Y_list[i] for i in range(len(X_list)) ]

def numpy_version():
    Z = X + Y

timer_obj1 = Timer("pure_python_version()", 
                   "from __main__ import pure_python_version")
timer_obj2 = Timer("numpy_version()", 
                   "from __main__ import numpy_version")

print(timer_obj1.timeit(10))
print(timer_obj2.timeit(10))  # Runs Faster!

print(timer_obj1.repeat(repeat=3, number=10))
print(timer_obj2.repeat(repeat=3, number=10)) # repeat to prove it!

结果如下:

0.0029753120616078377
0.00014940369874238968
[0.002683573868125677, 0.002754641231149435, 0.002803879790008068]
[6.536301225423813e-05, 2.9387418180704117e-05, 2.9171351343393326e-05]

可以看到,第二个输出的时间总是小得多,这就证明了这个性能优势是具有持久性的。

所以,如果你在做一些大数据研究,比如金融数据、股票数据的研究,使用Numpy能够节省你不少内存空间,并拥有更强大的性能。

参考文献:https://webcourses.ucf.edu/courses/1249560/pages/python-lists-vs-numpy-arrays-what-is-the-difference

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典

教你使用 Python 获取Fredapi美国重要经济指标数据

美国的金融市场(主要是股市、债市和汇市)经常受到其国内各项经济数据影响而波动。不仅如此,这些经济数据甚至会影响远在太平洋对岸的港股和A股。因此对于世界经济火车头的美国,我们要有对其经济数据有一定程度的理解。

对于股市而言,几个比较重要的经济指标为:

1. 联储局公开市场委员会会议声明

联储局公开市场委员会(FOMC)是决定美国利率走向的主宰者,而利率是美国经济未来增长的最重要因素,它的变化都会令消费支出、公司利润、政府预算及股票债券和美元的价值都受到影响。

2.消费者物价指数 Consumer Price Index (CPI)

这个指标是市场上最瞩目的经济指标之一,通胀(缩)率是联储局决定是否加息的最主要参考指标,而消费者物价指数则是最重要的通胀(缩)指标。通胀(缩)会影响到民生、政府的财政政策和民间的所有经济活动。通胀(缩)对于投资市场来说是件非常可怕的事情,因为它制造了经济的不稳定性和不确定性,给股市会带来波动和风险。

3.生产者物价指数 Producer Price Index (PPI)

跟CPI一样,这个指标是预测通货膨胀的重要指标之一,不过它反映的是生产者这个环节,是在通胀转移到消费者之前的数据,也就是说它对通胀和利率政策更具前瞻性,尽管其对消费者的影响力不如CPI。

4.采购经理人指数 Purchasing Managers Index (PMI)

PMI是一项全面的经济指标,概括了美国整体制造业状况、就业及物价表现,是全球最受关注的经济资料之一。采购经理人指数为每月第一个公布的重要数据,加上其所反映的经济状况较为全面,因此市场十分重视数据所反映的具体结果。在一般意义上讲采购经理人指数上升,会带来美元汇价上涨;采购经理人指数下降,会带来美元汇价的下跌。

5.非农就业数据 Non-farm Payrolls (NFP)

是美国非农业人口的就业数据,由美国劳工部每月公布一次,反应美国经济的趋势,数据好说明经济好转,数据差说明经济转坏。非农数据会影响美联储对美元的货币政策,经济差,美联储会倾向减息,美元贬值,经济好,美联储会倾向加息,美元升值。

本文将教你如何使用Python调用 FRED(Federal Reserve Economic Data) 数据库API获取以上相关数据。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install fredapi

2.注册账户获取FredApi权限

为了能够获取FRED的数据,你需要先注册账号、然后申请一个API秘钥,完全免费,三分钟就能解决。

进入FRED主页:https://research.stlouisfed.org

右上角有一个『My Account』,点进去后,选择『Create New Account』申请 FRED 账号:

注册完成后,会跳转到会员页,点击左侧API Keys:

申请API秘钥:

申请完毕后就能获得一个API Key了。

3.通过接口获取Fredapi经济指标数据

FRED 数据量非常庞大,其分为大分类和大分类的子项目。大分类我们可以通过这样的代码获得:

import requests
import pandas as pd
import datetime as dt
def fetch_releases(api_key):
    """
    取得 FRED 大分类信息
    Args:
        api_key (str): 秘钥
    """
    r = requests.get('https://api.stlouisfed.org/fred/releases?api_key='+api_key+'&file_type=json', verify=True)
    full_releases = r.json()['releases']
    full_releases = pd.DataFrame.from_dict(full_releases)
    full_releases = full_releases.set_index('id')
    # full_releases.to_csv("full_releases.csv")
    return full_releases

导出为CSV后,你能看到所有的大分类ID及其说明。

每个大分类中有许多子项目,比如 355:Minimum Wage Rates 底下会有:
* FEDMINNFRWG:Nonfarm Workers Minimum Hourly Wage
* FEDMINFRMWG:Farm Workers Minimum Hourly Wage

每一个子项目也有一个专属的『子项目英文代码』,就是前面的那串英文字。

我们可以通过对大分类进行关键字搜索,获取我们文首提到的五个指标:

from fredapi import Fred
import requests
import numpy as np
import pandas as pd
import datetime as dt


def fetch_releases(api_key):
    """
    取得 FRED 大分类信息
    Args:
        api_key (str): 秘钥
    """
    r = requests.get('https://api.stlouisfed.org/fred/releases?api_key='+api_key+'&file_type=json', verify=True)
    full_releases = r.json()['releases']
    full_releases = pd.DataFrame.from_dict(full_releases)
    full_releases = full_releases.set_index('id')
    # full_releases.to_csv("full_releases.csv")
    return full_releases

  
def fetch_release_id_data(release_id):
    """
    按照分类ID获取数据

    Args:
        release_id (int): 大分类ID

    Returns:
        dataframe: 数据
    """
    econ_data = pd.DataFrame(index=pd.date_range(start='2000-01-01', end=dt.datetime.today(), freq='MS'))
    series_df = fred.search_by_release(release_id, limit=3, order_by='popularity', sort_order='desc')
    for topic_label in series_df.index:
        econ_data[series_df.loc[topic_label].title] = fred.get_series(topic_label, observation_start='2000-01-01', observation_end=dt.datetime.today())
    return econ_data


api_key = '填入你的API秘钥'

fred = Fred(api_key)

full_releases = fetch_releases(api_key)

keywords = ["producer price", "consumer price", "fomc", "manufacturing", "employment"]

for search_keywords in keywords:
    search_result = full_releases.name[full_releases.name.apply(lambda x: search_keywords in x.lower())]
    econ_data = pd.DataFrame(index=pd.date_range(start='2000-01-01', end=dt.datetime.today(), freq='MS'))

    for release_id in search_result.index:
        print("scraping release_id: ", release_id)
        econ_data = pd.concat([econ_data, fetch_release_id_data(release_id)], axis=1)
    econ_data.to_csv(f"{search_keywords}.csv")

上面就是完整的数据下载代码,如果你想直接获取脚本文件,请在Python实用宝典后台回复:FRED 下载。

填入你申请的 API 秘钥,运行脚本,就能获取我们想要的五个指标数据。会在当前文件夹下生成相应关键词的csv文件。比如 employment.csv 的内容如下:

里面包含了就业相关的许多数据,包括我们关注的非农数据等。

如果你想要更换关键词下载其他关键词的数据,也可以在keywords中进行增删。请注意,这里搜索必须使用小写单词。

获取数据只是第一步,最重要的是如何分析这些数据与股市的相关性。

德意志银行有一个研究发现历年来ISM(即PMI)指数的数值和标普500的同比增长数值是高度相关的。

类似于这样的数据分析切入点是非常有意思的,大家也可以尝试基于这些数据做一些自己的研究分析,说不定会有意外的发现。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

​Python实用宝典 ( pythondict.com )
不只是一个宝典
欢迎关注公众号:Python实用宝典