All right and welcome back. In this session, we're going to do something interesting. We're going to actually develop the first of useful tool in our toolkit. So let's start as usual by going into a Python notebook. Let me make a little space here and so what are we going to do? We're going to basically develop code to compute Drawdowns. All right. So how are we going to do this? The first order of business is for us to get the data into Python. So this should be familiar, but let's do it from scratch. So what are we going to do? We're going to import Pandas. I don't think we'll use Numpy right now, so let's do Pandas as pd. Now remember what we have to do before, we have to use the read_csv functionality that's available to us in Pandas to be able to read a CSV. I'm going to read in the exact same data series that we read before. This is the set of monthly returns based on market equity or based on size. Because I want to access that same data that we had before, returns for large cap and small-scale stocks. So this is what we did last time. So this is should be familiar to you because this is just nothing more than exactly what we did in the last class. Let's also convert those, just extract the low 10 and the high 10. So this is the top decile and the bottom decile, and then let's rename the columns just as we did before. If there was a loss of three percent in a month. It actually said three rather than 0.03, so we're going to have to fix that. Let's see if all that worked by just plotting it. So all right. So I'm going to enter all that and if that worked out, that should work. Of course, we had this problem again where we might have to do that a second time. See if that fixes as. Otherwise, if that doesn't work, then I'll have to do the other thing and yeah that's it. This return series looks good. Is there anything that we want to fix here? Well, there's a couple of things I want to fix here. I don't like the fact that the index here is showing up as these integers. If you look at what we asked it to do, we said that the index column was zero and we told it to parse dates as true. So let's look and see if that really happened, and if you look at rets.head. So let's just look at the early part of rets. The index in fact got parse, but you can see it's doesn't look like a date to me. We can confirm that by looking at rets.index. So rets.index gives you just this series here. Let's look at that and you can see sure enough, it's an index and the dtype which is the data type of that series is int 64. That is not what we want. What we want is to treat that as datetime because we want to really treat this as a time series because if you treat this as a time series, you can do some really nice convenient things that I'll show you in a second. We'll make our lives a lot easier. So what you can do to fix that, re-assign that or you can change that. So what we'll do is there's a function available in Pandas that says to_datetime, and what that will do is you can give it a series. In this case, it's the same series, rets.index. But I'm going to tell it what the format is and I'll tell you exactly what you have to type here and then I'll explain to you how I came up with it. So what I'm going to do is I'm going to say the format that I've got here is percent y percent m. What is this percent y percent m? These are what are called formatting codes, and this is basically saying take this returns index, treat it as some date-time in this format; percent y percent m. So I'm telling it the format that this rets.index series is in and convert that to a datetime. Now, let me tell you exactly how I came up with this. What do you want to do is get familiar with the pandas documentation. So the simplest way to do that is pandas documentation, and you will get pandas.python.data.org and the documentation here at pandas. python.data.org is really pretty good. So for example, what we want to look at here is the API reference, and there are all these areas you can drill down into. What we want to look at is the general functions. These are functions that are built into Pandas that we can access. You can see that they've organized it by manipulations, top-level missing data, and the one we're looking at here is to_ datetime. So this is a top-level function that is available within Pandas and so we're able to access it right there to datetime. If you go into there, you get all the documentation. There would be some examples, and I'll give you things like that. So let's see if that worked and let's do rets.index and then let's look at rets.head again. You can see that now it is dates. So that's good, you can see that. If you look at rets.index, you'll see that it is now datetime. That's great. So the dtype is datetime64, 64 bit representation of a date and time. The only thing that bothers me a little bit is that this is a timestamp as off the first of that month. Well, this is actually the returns over the period of the month. So I can actually fix that as well by doing this rets.index is assigned. Okay. Now what I'm going to do is, I'm going to call a function on that, a method; rets.index.to_period, and to_periods says that each one of these timestamps should be treated as actually a period of a month. So this is a series, that is a method on a series. So it takes a series of dtype datetime and it converts it to a period which is a monthly periods. So let's look at what happens when I do that; rets.head. So now you can see it's actually doing the right thing in terms of tagging each one of these rows as a monthly return. Now because this is a datetime time-series, why did I do all this? Well, because now that it's a datetime time series, I can do some really cool things. For example, if I want to just look at the returns and say 1975, there you go. So you can give it this kind of shorthand notation to extract sections of this time series, and so we'll see a lot of other nice things that you can do with time series, and a time series is nothing more than a DataFrame or a series, where the index is of type datetime, and you can see that. So let's look at rets.index, and you'll see that this is of dtype period and period in turn is based on a datetime. Okay, good. So that's all just clean up stuff. We are exactly where we want to be. If you want a little bit more info on this return series, there's also a method that you can call called info and that will also give you useful information. So now, let's get down to the actual work. We're ready now to actually compute Drawdown. So let's do that, compute Drawdowns. So if you remember what are the three steps in computing the Drawdowns? The first is get computer wealth index. Then, once you've got the wealth index, you can compute previous peaks. Then, now that you've got the previous peaks, you can compute drawdown as a percentage, which is the wealth value as a percentage of the previous peak. Something like this. This was the basic idea that we talked about in class. This is what we're going to be doing now. Let's do this with large caps, just to start out. So what is the first step? Wealth index. Well, how do you compute the wealth index? The wealth index is nothing more than the value of a portfolio as it compounds over time. So let's start with $1,000. Let's say I'm going to start with $1,000. What I'm going to do now is, I'm going to compute the growth of a dollar over time. What is the growth of a dollar? It's nothing more than the compounded effect of each of the returns. So in other words, all I'm doing is 1 plus R. So we're going to do, I think, we're doing it with large cap, is that what we decided, yeah. So we're going to take the returns. We're going to convert it to this 1 plus R format, which is the growth of a dollar. So what I'm going to do is, I'm going to compute the cumulative products starting from the first return all the way through the last return. The way you do that is with something called cumprod. So let's just look at what it looks like. So wealth_index.head. So if you look at this, you can see that it starts off at $1,000 and then at the end of the first month it's gone up to 1,032, and then 71, and then 78, and then it goes down in October. You can also plot it if you want. Wealth_index.plot.line. Do a line plot, and you can see that it's going up over time. So far so good. All right. What's the next thing that we want to do? The next order of business, step 2, is what? Well, it was my little to-do list. Yeah. Step 2 there is, compute the previous peaks and then we can compute the drawdown. So now let's do that. Previous peaks, is what? You want to go over time, but you want to keep track of the cumulative max. What is the max that you have seen at any given point in time? So that is also available just by calling a method, and that is called cummax. So there's cummin and cummax. All we want to do here is, we want to compute the cummax. If we plot that, we should see, so plot.line and plot are exactly the same thing. So let's do that. You can see here that this is a line that never goes down. It's like this and keeps going up and then it's flat. When the actual wealth here drops off around 1999, you can see the wealth here is dropping off around 1999, but this thing keeps going. So the drawdown now is pretty simple. What is it? The drawdown is whatever wealth I have, right now, minus my previous peak, is the amount that I've lost. This is the amount I've drawn down. I don't want just the number. I don't want the dollars I've lost. I want the percentage loss as of my previous peak. So that is basically the number I'm looking at. So let's take a look at that and see what I get. So let me do that. You can see right away that this is basically what a typical drawdown diagram looks like. You can see that, "Wow, look at that." In the crash of 1929, people lost more than 80 percent of their wealth. More than 80 percent of their wealth was gone. So you're starting around here in 1929. In just a few years, you're looking at a loss of over 80 percent. Even when you go in 2009, you don't see that kind of a decimation as you saw in 1929. Well, let's put some numbers to these. So we've got the drawdown now, and we've seen it. So we can look at drawdown.min. Let's look at the head first and why is it min, you'll see in a second. So the drawdowns, basically, are numbers that are negative numbers, so you want the maximum drawdown, which means you want the lowest number, which is the min. So if I look at drawdown.min, you see that's 84 percent. Now, remember, drawdown is itself a time series. So what I can do now, if I want to look at the largest drawdown since 1975. So remember, if I want to slice it, what do I do? I have to put a colon so I say, from there to the end. So that is itself a series and I can compute the min of that. So what am I doing here? What I'm saying is give me the maximum drawdown since 1975, and you see a loss of almost 52 percent. Now you might be interested, well, when exactly did that happen? The way you do that is you don't want the min, you want the index of the min. Because remember, the index is the date. We want the index of the min because the index tells us when that happens. All I do is, I go in there and there's another method I can call idxmin. Idxmin says, find what the minimum is and this will return the minimum, which is what that does,.min does, return to me the index of the minimum. So I do that and you see that that index of the minimum happen in 2009-02. February 2009 was the worst point of that. If I just look over the entire period, drawdown.idxmin, that happened in 1932. So this is, of course, the big crash. Okay. Good. So we have now achieved a lot. We've been able to compute a drawdown of a series. This is the drawdown in the large cap stocks. But what if I told you, "Hey, can you tell me what the drawdown was in small cap stocks?" Well, the way we've done it, we've done everything here by just typing in things in the command line, I would have to go all the way to the beginning and I would have to start all over again and I would have to say, well, I'd have to recompute a new wealth index for this series. So I could do that, copy it and paste it, and then I can say small cap, and I could keep doing that stuff. But that's not really a smart way of doing it. So let's create our own function for the first time. So what I really want to do is, I just want to create a function where I can give it a series. What it will do for me is compute all these various things, like the drawdown, and the previous peak, and the wealth index so that I can plot them and I can do whatever I want. So the way you define your own function is just say def. Def is how you define a function, and then you give it a name. The name of my function is going to be drawdown. Now, my function is going to take some inputs. So what is the input I'm going to give it? I'm going to give it some sort of a return series. So return series. Now, in this case, you know that the return series is expected to be a Pandas series. So this part that I'm now typing in is optional but it's really good practice to do that. The way you can tell Python that it's a return series, but not just any return series, it's a return series which is of type pd.series. So if you do that, it's hinting to Python that I'm expecting really a series there, a panda series there as the input, and that's the sole input. Now, I have to give it what's called the body of the function, which is, okay, that's fine, what's called the signature of the function, which is the name and what parameters it's going to take. But let's actually implement the function. Let's implement the body of this function. How do I do that? So what I do is I hit Enter, and you can see here that the cursor has been indented. That's how in Python we construct blocks of code. So the way a function is defined in Python, you say def, you give the name of the function. You give any parameters within parentheses. You put a colon, and then below it, you give the body of the function, and the body of the function needs to be a block of code and so, you indent that block of code. What I'm going to do now before I do that, is I'm going to add a little documentation for the function. So I'm going to say the way I do that is I do this, what's called a docstring. A docstring is just documentation strings. So I'm going to give it a string and it's a string which is in triple quotes. That means, I can do multi-line. So I'm going to do a multi-line string and all I'm going to do here is just gives them a little bit of a hint. So I can say it takes a time series of returns, say, asset returns, computes and returns a dataframe that contains, what are the things we're going to send back? The wealth index, perhaps, the previous peaks, the percentage drawdown. Okay. So this stuff that I'm typing is nothing more than documentation. It's a really good practice to write this short one line, two line, three line documentation for every single function that you write. Now, what are we going to do? Well, we just do exactly what we did before. What did we do? We said wealth index is assigned to what? One thousand times one plus whatever this returns series is, and then what did we do? We did a cumprod of that. Remember that? Okay. Then what do you do? Then you compute the previous peaks, and the previous peaks is what? It's nothing more than the wealth index, and then the cummax of that, the cumulative max over that time series. Good so far? All right. Now we're in a position to compute the drawdowns. I'm going to call this variable drawdowns just because I want to make sure that this is different from the name of the function itself. So drawdowns is what? It is the wealth index minus the previous peaks as a percentage of the previous peak. Now that we've computed all the things we want to send back, I am going to send it back through the return statement. So anything I give here is going to be what is sent back to the caller of the function, all right? Now what did I say I'm going to send back? I am going to send back a Pandas DataFrame. So I'm going to do pd.DataFrame, and how do I send back the DataFrame? So the way I'm going to do this is, I'm going to send back three columns and the way you create a DataFrame out of three columns, if you remember, was to create a little dictionary with an entry per column. So that's what I'm going to do, so I'm going to say that. The first column, let's call it wealth. What am I going to do there? I'm going to pass back that series, the wealth index. The next thing I'm going to do is, I'm going to pass it back, let's call it peaks, and that is the previous peaks. Finally, the third column I'm going to send back is the drawdown, and that's what I've called drawdowns. That's it, my function is done. So I do Shift Enter, and hopefully I don't get any errors. I'm good. Now let's see if this works. Let's just do it with the previous return series that we already had and see if we get the same answer as we got before. We started with the LargeCap, so let's give it that. So I'm going to do drawdown, and I'm going to look at the returns LargeCap. That is going to give me back what? So let's look at the head of that, just to see whether it is in fact what we expect. You'll see that that's exactly what we got. We got back a DataFrame that over time, so it's a time series of the wealth of the peaks, the previous peaks, and the drawdown. Let's just plot two columns because the drawdown here is a percentage, and these two are dollar values. So let's look at this instead, wealth and peaks. So what am I doing? Drawdown is a DataFrame and then I'm giving it a list of columns, so if you're confused by this double square brackets, the way you should look at it is, drawdown is a DataFrame and I can give it a list of columns and the list is itself. So this square bracket is indexing drawdown and then I'm giving it as the index a list which is surrounded again by square brackets. So don't get confused by that, this is indexing and this is a list. So that should give you just those two columns. So just to be sure let's make sure that that is exactly what happens. That's obviously wrong. What I should have done is that. Let's look at this. That is the call, the call is going to return a DataFrame, the DataFrame I'm then indexing into that DataFrame and just pulling out these two columns, and I'm looking at the head of that. There you go, that does exactly what you'd expect. All right. So far so good. So if we've been able to do that, maybe we can even do this. So I'm going to do this, paste it here, and instead of looking at the head, let's see if we can plot it. Look at that. So it's giving you the wealth in blue, and it's giving you the peaks. You can see that's exactly what you would expect. The wealth is increasing, and then at that point, they're staying close to each other, and then when the market drops, the peak stays the same. Interesting that over here, over this period, that same thing is happening but you can't see it. So let's see if we can actually see that. So how would we do that? Let's say we wanted to do this exact same thing. So let me copy that and paste it, and let's say we wanted to do this exact same thing but we wanted to do it only over the period, let's say up to 1950. So how would you do that? Instead of just rets LargeCap, what you would do is, you would look that rets is a time series, so we can do up to 1950. So you see what's going on? Instead of just doing it with all of rets, which is what I had before, I am now doing just that section, that slice of rets. Let's see if that worked. There you go, exactly what you would expect, and you can see that the drawdown here is in dollar terms, not as great as it was there, but that's only because you only had about $2,000. You'd start with $1,000 and you only got up to about 2,500 before you lost 80 percent of it. Over here, the dollar drop is much higher even though as we saw, the percentage drops are much lower. So let's look at that. Let's see if we can reproduce those numbers. Do exact same thing. Okay. So what are we going to do here? We're going to look at the LargeCap over the whole period, we're going to compute the drawdown, that's good. So if you look at the head of this, you'll see that this has the wealth, the peaks, and the drawdown. So let's just look at the drawdown here. So I'm going to do exactly that. So now, let's look at the drawdown of that LargeCap over the entire period. Then what we want to do, is we want to find the minimum of that, and you'll see that it's 84 percent. Now because it's a function, all I have to do if I want to look at SmallCap, is I just have to pass it a different return series. So all I do is change that instead of calling drawdown. So what am I doing here? Let's understand what's going on. I'm calling my function drawdown and I'm passing that as the return series. Here, I'm just swapping out the return series and I'm giving it a different column, and if I hit enter, you'll see that I've got almost the same thing. So what you can see here is that the percentage drawdowns were almost identical for LargeCap and SmallCap. Now when exactly did that happen? The damage done to the stock market when this happened was pretty much uniform, regardless of whether it was SmallCap or LargeCap. So let's check when that happened. That was 1932. If I look at when this LargeCap thing happened, it also happened in 1932. Now let's see, was the damage between SmallCap and LargeCap the same in the next big crash? So let's do the exact same thing. So let's look at drawdown. Let's look at drawdowns in SmallCap since 1940 onwards. All right. So first, let's look at what it was. That was about 70 percent. When did that happen? Idxmin, that happened in 1974. So there was clearly some sort of a crash that happened in 1974. Let's look at the crash scenes, let's say 1975. You'll see that that was a 63 percent crash. When did that happen? That happened in 2009. Now, what was the damage done in LargeCaps? Fifty-two percent. Did that happen at the same time? Well, same thing, exact same thing. We go on there, say idxmin, there you go. So the beauty of writing our own function is that we can call it with all sorts of different arguments, we can call it with different return series. That way, we don't have to retype in all that stuff just because I want to go from SmallCap to LargeCap. So I think our next order of business is to take this function that we've created and start building a toolkit of functionality, that means we're going to build our own module in our next class. Thank you, I'll see you there.