操作的回撤
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作的回撤相关的知识,希望对你有一定的参考价值。
参考技术A 本文演示了下列命令的常见使用方式:清除工作区所有未纳入版本管理的目录、文件。
git clean -f :强制清除工作区根目录下未纳入版本管理的文件。
git clean -d -f :强制清除未纳入版本管理的目录和文件,会从根目录递归所有子目录。
git checkout <file> :撤销工作区指定文件的修改。用该文件暂存区的快照替换(如果该文件是untracked的,此命令不会处理)。
git checkout HEAD <file> :撤销指定文件在工作区和暂存区的所有修改,用版本库最近一次提交的版本来替换。
以gitsample的README.md文件为例。当前此文件的内容:
我们在文件中新加入一行文字,内容变成:
此时在Git bash命令行中使用 git diff 比较下工作区和暂存区文件的差异:
接下来撤销工作区的修改:
再来查看差异:
工作区和暂存区没有差异了,README.md文件也变回最初的内容,刚才对工作区README.md文件的操作成功的被撤回了。
git reset HEAD [--] <paths>... :撤销指定路径在暂存区的尚未提交到版本库的内容。如果指定的路径从未提交到版本库,那么就直接将该路径从暂存区撤销;否则会用该路径在版本库中最近一次的提交来覆盖该路径的暂存区。
git reset --soft [<commit>] :撤销版本库到指定的commit id。可以用HEAD来代替commit id:HEAD^代表回撤最近一次的提交(和HEAD~1等效),HEAD^^表示回撤最近两次(和HEAD~2等效),以此类推;
git reset --mixed [<commit>] :撤销版本库提交和暂存区到指定的commit id。--mixed是默认参数, git reset --mixed HEAD^ 和 git reset HEAD^ 等效;
git reset --hard [<commit>] :撤销版本库、暂存区和工作区到指定的commit id。注意:此命令会直接撤销工作区的修改,这个操作是不可逆的!使用之前最好用git status来比较下确认工作区的修改可以放弃。
我们先在gitsample仓库中准备一下数据:
在文件夹内新建一个demo_reset.txt文件;
在文件内增加一行“Rev. 1”保存、在Git bash中运行 git add . 、 git commit -m "demo reset Rev. 1" 将文件提交到版本库;
在文件内增加一行“Rev. 2”保存、 git add . 、 git commit -m "demo reset Rev. 2" 将文件提交到版本库;
在文件内增加一行“Rev. 3”保存、 git add . 、 git commit -m "demo reset Rev. 3" 将文件提交到版本库。
然后再文件内增加一行文字“Rev. 4”、然后 git add . 添加到暂存区。此时使用 git diff demo_reset.txt 查看状态:
从diff信息可以看到工作区的文件和暂存区的比较起来没有不同。此时回撤暂存区的操作:
然后再执行 git diff 查看:
从diff的结果来看暂存区的内容已经回撤了,和工作区的文件已经不一样了。
接下来通过练习看下下 git reset --hard [<commit>] 的效果:
命令的返回信息提示版本库已经回撤到“demo reset Rev. 2”这一次的提交了,看下git status的结果:
工作区和暂存区、暂存区和版本库都是一致的。说明暂存区和工作区的操作也都回撤了。用记事本打开文件会发现内容也只有Rev. 1和Rev. 2两行了。
接下来在Git bash中运行 $ git reset --soft HEAD^ ,然后用 git status 看下效果:
可以看到,暂存区的demo_reset.txt有待提交的内容了。此时暂存区和工作区的文件内容都有Rev.1和Rev.2,而版本库已经回撤到Rev. 1这个版本了。如果现在又想将版本库回到最初的提交(或者过程中的某次提交),应该怎么办呢?还是使用reset命令,只要直到目的版本的commit id就能够返回。可以通过 git log --reflog -3 (只返回最近3次的提交操作)查看commit id:
可以看到Rev. 3版本的commit id是 df531846649c39baa68784ee40c907dd58e5c7da 。现在将版本库的提交返回到这里:
从返回的结果可以看到,版本库的最近一次提交已经返回到Rev. 3了。
有时候我们提交完了才发现有几个文件应该一起提交但是忘记添加,或者有的文件不应该提交,又或者提交的信息写的有问题。此时想修正这个问题,不想将原本应该在一起提交的变成两次提交,可以使用 git commit -amend 命令。
先要将需要一起提交的文件加入到暂存区,将不应该提交的文件撤回到原先的状态。然后在Git bash中运行命令:
命令运行后会启动文本编辑器,提示修改commit message:
将原来的message”demo reset Rev. 3“修改为“demo reset Rev. 3 --amend”。然后退出文本编辑器。
从命令行返回结果可以看到,提交已经覆盖。我们再用 git log --reflog 验证下:
对比下之前的log:
可以明显的看到, git commit --amend 命令运行后,并没有新增一条提交操作,而是覆盖了最近一次的提交:commit id和message都被替换了。
需要注意的是 git commit --amend 命令会改变最近一次提交的commit id,所以当最近一次的提价已经推送到远程仓库之后,要特别谨慎的使用这个命令,否则容易引起同其它开发人员的版本冲突。
Python 中最大回撤的开始、结束和持续时间
【中文标题】Python 中最大回撤的开始、结束和持续时间【英文标题】:Start, End and Duration of Maximum Drawdown in Python 【发布时间】:2014-05-01 16:29:20 【问题描述】:给定一个时间序列,我想计算最大回撤,我还想定位最大回撤的起点和终点,以便计算持续时间。我想在时间序列图上标记回撤的开始和结束,如下所示:
到目前为止,我已经获得了生成随机时间序列的代码,并且已经获得了计算最大回撤的代码。如果有人知道如何识别回撤开始和结束的地方,我将不胜感激!
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# create random walk which I want to calculate maximum drawdown for:
T = 50
mu = 0.05
sigma = 0.2
S0 = 20
dt = 0.01
N = round(T/dt)
t = np.linspace(0, T, N)
W = np.random.standard_normal(size = N)
W = np.cumsum(W)*np.sqrt(dt) ### standard brownian motion ###
X = (mu-0.5*sigma**2)*t + sigma*W
S = S0*np.exp(X) ### geometric brownian motion ###
plt.plot(S)
# Max drawdown function
def max_drawdown(X):
mdd = 0
peak = X[0]
for x in X:
if x > peak:
peak = x
dd = (peak - x) / peak
if dd > mdd:
mdd = dd
return mdd
drawSeries = max_drawdown(S)
MaxDD = abs(drawSeries.min()*100)
print MaxDD
plt.show()
【问题讨论】:
您可能对此感兴趣:***.com/questions/21058333/… 这里有一个类似的问题有一个有用的答案(虽然对于熊猫):quant.stackexchange.com/questions/55130/… 【参考方案1】:只要找出运行最大值减去当前值最大的地方:
n = 1000
xs = np.random.randn(n).cumsum()
i = np.argmax(np.maximum.accumulate(xs) - xs) # end of the period
j = np.argmax(xs[:i]) # start of period
plt.plot(xs)
plt.plot([i, j], [xs[i], xs[j]], 'o', color='Red', markersize=10)
【讨论】:
实现最大回撤的真正干净解决方案! 如果你不介意,你能解释一下 i 和 j 的代码吗? For i: np.maximum.accumulate(xs) 为我们提供了累积最大值。取那个和 xs 之间的差并找到它的 argmax 给我们提供了累积回撤最大化的位置。然后对于 j: xs[:i] 获取从周期开始到 i 点的所有点,最大回撤结束。 np.argmax(xs[:i]) 找到图中最高(最大)点的位置/索引,直到该点,这就是我们正在寻找的峰值。 如果没有回撤(所有点都高于前一个),此方法会抛出错误。应检查 i == 0 是否为 true,则回撤也为 0 能否请您展示如何将真实的“日期”添加到此缩编图的 x 轴?到目前为止,代码有效,但仅适用于 numpy 数组。如果时间序列以带有时间戳作为索引的 pandas 系列的方式出现怎么办?换句话说,在情节上显示真实日期会非常好,这样您就可以了解您看待事物的时间范围。谢谢!【参考方案2】:如果这对任何人有帮助,我添加了水下分析...
def drawdowns(equity_curve):
i = np.argmax(np.maximum.accumulate(equity_curve.values) - equity_curve.values) # end of the period
j = np.argmax(equity_curve.values[:i]) # start of period
drawdown=abs(100.0*(equity_curve[i]-equity_curve[j]))
DT=equity_curve.index.values
start_dt=pd.to_datetime(str(DT[j]))
MDD_start=start_dt.strftime ("%Y-%m-%d")
end_dt=pd.to_datetime(str(DT[i]))
MDD_end=end_dt.strftime ("%Y-%m-%d")
NOW=pd.to_datetime(str(DT[-1]))
NOW=NOW.strftime ("%Y-%m-%d")
MDD_duration=np.busday_count(MDD_start, MDD_end)
try:
UW_dt=equity_curve[i:].loc[equity_curve[i:].values>=equity_curve[j]].index.values[0]
UW_dt=pd.to_datetime(str(UW_dt))
UW_dt=UW_dt.strftime ("%Y-%m-%d")
UW_duration=np.busday_count(MDD_end, UW_dt)
except:
UW_dt="0000-00-00"
UW_duration=np.busday_count(MDD_end, NOW)
return MDD_start, MDD_end, MDD_duration, drawdown, UW_dt, UW_duration
【讨论】:
【参考方案3】:behzad.nouri 解决方案非常干净,但它不是最大提取时间(无法发表评论,因为我刚刚开设了我的帐户并且我没有足够的声誉 atm)。
您最终得到的是名义价值的最大下降,而不是价值的相对下降(百分比下降)。例如,如果您将此应用于长期上升的时间序列(例如股票市场指数标准普尔 500 指数),则最近的价值下降(较高的名义价值下降)将优先于较早的价值下降,因为只要名义价值/点的下降幅度更大。
例如标准普尔 500:
2007-08金融危机,下跌56.7%,888.62点 近期冠状病毒危机,下跌 33.9%,1,1148.75 点通过将此方法应用于 2000 年之后的时期,您将看到冠状病毒危机而不是 2007-08 年金融危机
以下相关代码(来自 behzad.nouri):
n = 1000
xs = np.random.randn(n).cumsum()
i = np.argmax(np.maximum.accumulate(xs) - xs) # end of the period
j = np.argmax(xs[:i]) # start of period
plt.plot(xs)
plt.plot([i, j], [xs[i], xs[j]], 'o', color='Red', markersize=10)
您只需将该名义值的下降除以最大累积量即可获得相对 (%) 下降。
( np.maximum.accumulate(xs) - xs ) / np.maximum.accumulate(xs)
【讨论】:
【参考方案4】:您的 max_drawdown 已经记录了峰值位置。修改if
,使其在存储mdd时也存储结束位置mdd_end
,以及return mdd, peak, mdd_end
。
【讨论】:
【参考方案5】:我同意 k0rnik。
证明 behzad.nouri 给出的公式可能产生错误结果的简短示例。
xs = [1, 50, 10, 180, 40, 200]
pos_min1 = np.argmax(np.maximum.accumulate(xs) - xs) # end of the period
pos_peak1 = np.argmax(xs[:pos_min1]) # start of period
pos_min2 = np.argmax((np.maximum.accumulate(xs) -
xs)/np.maximum.accumulate(xs)) # end of the period
pos_peak2 = np.argmax(xs[:pos_min2]) # start of period
plt.plot(xs)
plt.plot([pos_min1, pos_peak1], [xs[pos_min1], xs[pos_peak1]], 'o',
label="mdd 1", color='Red', markersize=10)
plt.plot([pos_min2, pos_peak2], [xs[pos_min2], xs[pos_peak2]], 'o',
label="mdd 2", color='Green', markersize=10)
plt.legend()
mdd1 = 100 * (xs[pos_min1] - xs[pos_peak1]) / xs[pos_peak1]
mdd2 = 100 * (xs[pos_min2] - xs[pos_peak2]) / xs[pos_peak2]
print(f"solution 1: peak xs[pos_peak1], min xs[pos_min1]\n rate :
mdd1\n")
print(f"solution 2: peak xs[pos_peak2], min xs[pos_min2]\n rate :
mdd2")
此外,资产的价格不能为负数,所以
xs = np.random.randn(n).cumsum()
不正确。最好添加:
xs -= (np.min(xs) - 10)
【讨论】:
【参考方案6】:这个解决方案已经过测试并且有效,但这里我计算的是最大持续时间回撤,而不是最大回撤的持续时间。该解决方案可以轻松调整以找到最大回撤的持续时间。
def max_dur_drawdown(dfw, threshold=0.05):
"""
Labels all drawdowns larger in absolute value than a threshold and returns the
drawdown of maximum duration (not the max drawdown necessarily but most often they
coincide).
Args:
dfw (pd.DataFrame): monthly data, the pre-computed drawdowns or underwater.
threshold (float): only look at drawdowns greater than this in absolute value e.g. 5%
Returns:
dictionary containing the start, end dates and duration in months for the maximum
duration drawdowns keyed by column name.
"""
max_dur_per_column =
columns = dfw.columns.copy()
mddd_start =
mddd_end =
mddd_duration =
for col in columns:
# run the drawdown labeling algorithm
dfw['sign'] = 0
dfw['sign'].loc[dfw[col] == 0] = +1
dfw['sign'].loc[dfw[col] < 0] = -1
# find the sign change data points
dfw['change'] = dfw['sign'] != dfw['sign'].shift(1)
# the first change doesn't count
dfw['change'].iloc[0] = False
# demarcate the lef and right of the drawdowns
left = dfw[(dfw['change'] == True) & (dfw['sign'] == -1)].index.values
right = dfw[(dfw['change'] == True) & (dfw['sign'] == 1)].index.values
min_len = min(len(left), len(right))
intervals = pd.IntervalIndex.from_arrays(left[0:min_len], right[0:min_len])
# find the minimum value per drawdown interval so we label all data points to the left of it.
min_per_int = list(map(lambda i: (i.left, i.right, dfw[col][(dfw.index >= i.left) & (dfw.index < i.right)].min()), intervals))
# filter out drawdowns lower in absolute value than a threshold
min_per_int = list(filter(None.__ne__, list(map(lambda x: None if x[2] >= -threshold else x, min_per_int))))
# label only the negative part of the underwater NDD stands for negative-side drawdown.
dfw['NDD'] = 0
mddd_start[col] = None
mddd_end[col] = None
mddd_duration[col] = 0
for i in min_per_int:
# find the index of the data point that is minimum this is an argmin
min_idx = dfw[(dfw.index >= i[0]) & (dfw.index < i[1]) & (abs(dfw[col] - i[2]) < 1e-15)].index[0]
# compute the duration and update the maximum duration if needed
tmp_dur = int(np.round((min_idx - i[0]) / np.timedelta64(1, 'M')))
if tmp_dur > mddd_duration[col]:
mddd_start[col] = i[0].date()
mddd_end[col] = min_idx.date()
mddd_duration[col] = tmp_dur
return mddd_start, mddd_end, mddd_duration
示例用法:
# compute cumulative returns
dfc = pd.DataFrame(dfr['S&P500'] / dfr['S&P500'][0])
# compute drawdowns
dfw = dfc / dfc.cummax() - 1
print(max_dur_drawdown(dfw))
【讨论】:
以上是关于操作的回撤的主要内容,如果未能解决你的问题,请参考以下文章