Pairs-trading strategy from scratch in Python — Transcript
Full transcript
- 0:00today I'm going to write a Paris trading
- 0:02strategy which is the basic strategy
- 0:04that Edward thorb used to make his 800
- 0:07million Fortune I've been obsessed with
- 0:09this strategy ever since I read his book
- 0:11called A man for all markets a few years
- 0:13ago and realizing that not only this guy
- 0:16beat the casino by inventing card
- 0:18counting but he also beat the stock
- 0:20market with the strategy not only his
- 0:22fund was profitable almost every single
- 0:24month but his worst monthly loss was
- 0:26less than 1% it's a market neutal
- 0:29strategy which means potentially we can
- 0:31make money whether if the price is in an
- 0:33uptrend A downtrend or even in a Range
- 0:35I'm going to show it on a chart in a
- 0:36second but then I will also show the
- 0:38basic math behind it in a Jupiter
- 0:40notebook and then we will write it
- 0:42inside Jesse so we can run some back
- 0:44test and see some actual results so if
- 0:46that sounds interesting let's get right
- 0:48into
- 0:49it all right let's begin with a very
- 0:51simple example ethereum versus ethereum
- 0:54classic they have different price ranges
- 0:56ethereum is in matter of thousands of
- 0:59dollars but ethereum classic is I think
- 1:01in hundreds but we know their prices are
- 1:04highly correlated and that's really what
- 1:06we care about so for example on this
- 1:08chart I have both their prizes and I've
- 1:11set it to be on the same priz scale just
- 1:13so that we can see them easier and you
- 1:16can see for example in here the price of
- 1:18ethereum is actually lower than the
- 1:20price of ethereum classic but it becomes
- 1:23the opposite in here the price of
- 1:25ethereum is actually more than the price
- 1:27of ethereum classic so what does it mean
- 1:29it means that if we open the long
- 1:31position for ethereum at this point in
- 1:33time and at the same time open the short
- 1:36position for ethereum classic here and
- 1:38hold that position when we reach this
- 1:40point in time you can see that it's the
- 1:43opposite now the price of ethereum
- 1:45classic is lower than the price of
- 1:47ethereum so what does it mean it means
- 1:48that yes both the prices are lower than
- 1:51what it was at this point in time but if
- 1:53we opened two opposite side positions
- 1:56one long and the other one short at this
- 1:59point we would have made money why
- 2:01because our short position would have
- 2:03made more money than the amount that our
- 2:06long position lost so the difference
- 2:08between the panl of both positions would
- 2:11be our profit now if I go back in time
- 2:13you can find so many positions where
- 2:15this opportunity existed I'm going to
- 2:17explain the math behind this strategy in
- 2:19a second with some code but I want to
- 2:21mention that this video right here by
- 2:23copian is very initially learned about
- 2:26the math behind it and in my video I
- 2:28won't go to as much detail as they did
- 2:31so definitely check out their video if
- 2:33you want to learn about this topic in
- 2:35more details all right so first I'm
- 2:37going to show you the basics of parist
- 2:39trading in a Jupiter notebooks which is
- 2:40great for a presentation and in case you
- 2:42didn't know if you want to use jupyter
- 2:44notebooks with Jesse all you need to do
- 2:46is to make sure they are inside your
- 2:48Jesse project all right so my project is
- 2:50named but I have multiple Jupiter
- 2:53notebooks and this one is the one I'm
- 2:55going to use all right so first we need
- 2:57to select the kernel and I'm going to to
- 2:59select one which already has Jessi
- 3:02installed in it all right let's add a
- 3:04code block and first I'm going to import
- 3:06all the necessary packages so I'm going
- 3:08to say from Jesse import utils and the
- 3:12research module now the utils will give
- 3:15us some utility functions and the
- 3:16research module is used for importing
- 3:19data from the database or even running
- 3:20back test but I'm not going to use that
- 3:22in jupyter notebooks in this video but
- 3:24you can if you like to all right so next
- 3:27I'm going to import JC helpers as JH
- 3:30which will give me some helpers that
- 3:32aren't really used in most of the
- 3:34strategies but I'm going to use it in
- 3:36here next I will import numpy as MP from
- 3:40daytime I'm going to import daytime and
- 3:43lastly I'm going to import the Matt plot
- 3:46Li library because I'm going to show you
- 3:49some charts all right next I want to
- 3:50import some data and I'm going to use
- 3:52the research modules get candles
- 3:54function and first it will ask me the
- 3:57name of the exchange all right so let's
- 3:59def find the exchange variable here I'm
- 4:02going to use binance Perpetual Futures
- 4:05and here I will pass the exchange the
- 4:08second one is the symbol and I want to
- 4:10use eth and Etc which is ethereum
- 4:13classic all right so the first one is
- 4:15going to be e us and the time frame I
- 4:18want it to be 15 minutes and then we
- 4:21have the assort now the assort date that
- 4:24is accepted here has to be in time stamp
- 4:26format and to convert that I'm going to
- 4:29use use the helper function from Jesse
- 4:31so I'm going to say this start date
- 4:34equals and I'm going to use date to Tim
- 4:36stamp and in it I will pass the date
- 4:40since
- 4:422024 the month could be the 10th month
- 4:45and since the first day and for my
- 4:48finished date I'm going to give it again
- 4:51date to timestamp again 2024 10th month
- 4:55and the third day so I only want data
- 4:58for 2 days B basically all right so now
- 5:01I have the start date right and the
- 5:04Finish date all right so and I can leave
- 5:07the other ones all right now this
- 5:08function will return two values the
- 5:10warm-up candles and the actual candles
- 5:12that I want and because I don't intend
- 5:14to run back test with it in this Jupiter
- 5:17notebook I don't care about the value
- 5:19for the V candles right so I don't want
- 5:21the first one and that's why I'm using
- 5:23this underline value here but the second
- 5:25one I will call it C1 or candle one and
- 5:28there we go now for the second one we're
- 5:31going to do the same thing right except
- 5:34instead of eth we want it to be Etc all
- 5:36right let's run this and it's all good
- 5:38now next because I want to show you a
- 5:40chart of these values I'm going to need
- 5:42time stamps so I'm going to create an
- 5:45empty list called times and I'm going to
- 5:48Loop through the first set of candles
- 5:51right and in it I will simply say times
- 5:53do pend and date time do from time stamp
- 5:57and then I will pass the time stamp of
- 5:59each candle and that would be the first
- 6:01index but because this function expects
- 6:03the time samps to be in seconds but
- 6:05Jess's times samps are in milliseconds
- 6:08I'm going to have to divide this by
- 6:111,000 all right there's one more thing I
- 6:12need to do just like this chart that I
- 6:14just showed you which both prices were
- 6:16on the same price scale because they
- 6:18weren't absolute values of prices they
- 6:20were price changes in matter of
- 6:23percentage right so we need to do the
- 6:25same in our python code so I'm going to
- 6:27say C1 equals use
- 6:30do prizes to returns and this is an
- 6:33already built-in function in Jesse so I
- 6:35don't have to Define it from scratch
- 6:37which is really nice so in it I'm going
- 6:39to have to pass all the candles but I
- 6:42only want the closing prizes and that
- 6:44would be C1 and I'm going to select all
- 6:47the candles but then I'm going to select
- 6:49only the closing candles and that would
- 6:51be the index of two so in case you
- 6:53didn't know the zero index in Jesse is
- 6:55timestamp and then we have the open
- 6:58close high low and then volume so the
- 7:00close would have an index of two and
- 7:02then I'm going to do the same thing for
- 7:04the second price data or ethereum
- 7:06classic right and we should also change
- 7:08this all right now we can run this one
- 7:10okay we're getting an error all right
- 7:12this shouldn't have been there it should
- 7:14have been inside here all right so now
- 7:15we can finally plot the actual price
- 7:17data and for that I'm going to say PLT
- 7:20figure which is used to set the size of
- 7:22the chart and in it I'm going to say fix
- 7:24size equals 15x 6 now this Size Doesn't
- 7:27Really Matter much it's just for
- 7:29presentation you can set whatever value
- 7:31you like next I'm going to say PLT do
- 7:33plot and I'm going to pass the time
- 7:36stamps and then the actual price data
- 7:39and for color I'm going to say blue and
- 7:42the label is going to be e next I will
- 7:45do the same thing for ethereum classic
- 7:47and I'm going to set the color as red
- 7:49and this should be TC and finally I can
- 7:52do pl. Legend to show me everything all
- 7:55right so now we can see the price data
- 7:57for both the assets on the same chart
- 8:00which is really cool now if you pay
- 8:02close attention you can see that our
- 8:04Theory very much sounds right in here
- 8:07for example the price of eth was lower
- 8:09than Etc but in here it was higher than
- 8:13that so in other words if we open the
- 8:15long position here and shorted the price
- 8:18of Etc and did the opposite in here we
- 8:21would have made money and the same goes
- 8:23for so many other places it goes here it
- 8:26goes here here here so it just continues
- 8:29right which is very promising all right
- 8:30so now that we have both of them on the
- 8:33same chart we should begin writing the
- 8:35actual code based on math that we can
- 8:37actually use to trade it right because
- 8:40we're not going to have the chart when
- 8:42we are trading this with a bot right now
- 8:44we're looking at this chart with our
- 8:46eyes that's how we know this happening
- 8:48so we need to use statistics to come up
- 8:50with a good strategy the first step is
- 8:52that we need the spread in other words
- 8:55we need the difference between the two
- 8:56price data so I'm going to define a
- 8:59spread as C1 and then I'm going to
- 9:02select since the first candle up until
- 9:04the end and the reason I'm doing this is
- 9:06how we defined this C1 variable we
- 9:09defined it in here we converted the
- 9:11candles into returns and when we did
- 9:14that the First Data actually became a
- 9:16nan value and that's why I'm doing this
- 9:18and if you don't believe me I can print
- 9:20this data so you can see it so let's
- 9:22print the first value and you see it is
- 9:25Nan right and we cannot really have that
- 9:27in our strategy so that's why I'm going
- 9:30to select since the first data and when
- 9:33I say first I mean the index of one
- 9:35because the actual first value would
- 9:37have the index of zero so we're going to
- 9:39select this one until the end minus C2
- 9:43and again selecting since the first
- 9:45index up until the end right so this is
- 9:47going to be our spread which is the
- 9:49difference between the two price data
- 9:51now to actually take advantage of this
- 9:53data having the spread alone isn't
- 9:55enough we need the zcore of it now what
- 9:58is zcore the Z score is the price
- 10:00difference or the spread that we just
- 10:02defined compared to the mean of the
- 10:04price data and that's what we really
- 10:05care about so we're going to define the
- 10:07zscore now Jesse already has a utility
- 10:10function which will calculate the zscore
- 10:12for me so I'm going to use that one it's
- 10:14called zscore and it takes the series
- 10:17data or in this case it would be our
- 10:19spread now I'm going to also Define the
- 10:21mean now by the way the zcore function
- 10:24it will use the mean itself if you're
- 10:26curious to know how it works is it's
- 10:28basically this price series minus the
- 10:31mean of that price series divided by its
- 10:34standard deviation right now you don't
- 10:36have to know about the exact math behind
- 10:38it you could just use it but knowing it
- 10:40certainly helps all right so I am also
- 10:43going to define the mean of it myself
- 10:45because I want to print it on the chart
- 10:47and for that we can use numpy and we
- 10:49will just pass the zscore and now we can
- 10:52plot them right so first I'm going to
- 10:55say PLT
- 10:57figure and then pass the fix size just
- 11:00like before 15 and six next I'm going to
- 11:03say PLT plot and I'm going to pass the
- 11:07times again selecting since since the
- 11:09index of one to SK skip that Nan value
- 11:12and then I'm going to pass the zcore I'm
- 11:14going to set the color to Blue and the
- 11:17label could also be Z score next we're
- 11:19going to plot a horizontal line using
- 11:21this index and I'm going to pass the
- 11:23mean that we just defined here I'm going
- 11:26to use the color black and set the line
- 11:28Style to Dash and the label is going to
- 11:32be mean and then I'll do it two more
- 11:34times for the values of 1.2 and minus
- 11:381.2 with colors of red and green all
- 11:41right so let's see how this looks like
- 11:43and there we go so now we have the zore
- 11:45of the two price series and we can see
- 11:48how their correlation or the related
- 11:52price is actually moving so for example
- 11:54in here we can long the first asset and
- 11:56short the other one and when it reaches
- 11:59the mean we will just close the
- 12:01positions and we can do the opposite
- 12:03when the zscore goes above this line we
- 12:05can short the first asset and long the
- 12:08second one and again when it reaches the
- 12:10mean we can just close it right and and
- 12:13as you can see we had opportunities for
- 12:15this type of trade in more than once we
- 12:17had it here we had it here here here
- 12:21here here and so much more right so it
- 12:24looks very promising but here's the
- 12:26thing though right now we have this data
- 12:29honest beautiful chart which is only
- 12:31showing us the price data for two days
- 12:33but in reality we're not going to have
- 12:35charts we're going to trade this with a
- 12:37butt right so we need a statistical way
- 12:40to write all of these things but not
- 12:42only that we need to make sure these
- 12:44prizes are actually cointegrated now
- 12:46what is congration well again this video
- 12:49will describe it so much better but I'm
- 12:51also going to try my best you see to
- 12:53trade any mean verion strategy we need
- 12:55that price data to be stationary and
- 12:57what is a stationary well it means that
- 13:00the mean of that price data or data
- 13:03series is not moving now what is a
- 13:04stationary it means that the mean of the
- 13:07price data or data series is stable it's
- 13:11not changing because right now in this
- 13:13picture we know the mean is this but
- 13:16that's because we already have the price
- 13:18data for 2 days right so for example at
- 13:21this point in time the mean wouldn't
- 13:24exactly have been this value or at this
- 13:26point in time it wouldn't exactly have
- 13:28been that because we would would have
- 13:29calculated based on this much data right
- 13:31but now that we have all of it we
- 13:33already know what the mean of it is
- 13:35right so if I try to calculate the mean
- 13:38of this data series is going to change
- 13:40now we don't want it to be like stable
- 13:43100% to be able to trade but the thing
- 13:45is if we try to trade a mean verion
- 13:47strategy on let's say just one asset we
- 13:50know for sure that it is not going to be
- 13:52a stationary however we can still trade
- 13:54them if they are conr and what does
- 13:57congration mean it means that yes these
- 14:00two price data even though individually
- 14:02they're not stationary some kind of
- 14:04combination of their price data which in
- 14:07this case would be the zcore that we
- 14:09just calculated that series is a
- 14:11stationary so that's what it means right
- 14:14and if that's the case then we can trade
- 14:16them against each other but if they're
- 14:18not we just can't now there are some
- 14:20statistical ways to calculate this but
- 14:22again Jesse gives us a utility function
- 14:24which will take care of this so I'm
- 14:26going to use that one so let's define a
- 14:28new variable called is cointegrated and
- 14:32in it we're going to use the r
- 14:34cointegrated utility function and first
- 14:37we will pass the first priz data and
- 14:38then the second now let's print this and
- 14:41it is returning true so now we know they
- 14:44are qur now if you're curious to know
- 14:46the source code of this well here it is
- 14:48we're using the set model module of
- 14:51python and then we use the P value and
- 14:54if it is below the cut of value we say
- 14:56it is cointegrated otherwise it's not
- 14:59now I know this sounds confusing but
- 15:01again watch that video of copian and
- 15:04hopefully it should make it clearer
- 15:06right now let's move on to Jesse so we
- 15:08can write the code in it so we can run
- 15:10some backst and see some actual numbers
- 15:12all right I'm going to start by
- 15:13generating a new strategy and I'm going
- 15:15to call it P
- 15:18trading all right so now I'm going to
- 15:20copy this and I will open my CER editor
- 15:24which uses Ai and is so much smarter and
- 15:26faster to use and I'm going to look for
- 15:29for this all right so this is the
- 15:30generated code now the real challenge
- 15:32for this strategy is that we cannot only
- 15:35Define it inside one strategy file
- 15:38because if I try to run a back test you
- 15:41see we have these routes and right now
- 15:43it is set to BC so let's change this to
- 15:46East UCC and the time frame to 15
- 15:50minutes and this one to P trading all
- 15:54right and the duration is since
- 15:56beginning of this year until just if you
- 15:59days ago now here's the thing though we
- 16:00need to trade this for both eth and
- 16:03ethereum classic so I need to add
- 16:05another trading route and for this one
- 16:07I'm going to choose Etc and the same
- 16:11time frame but now we need to also pick
- 16:13another strategy so picking this one
- 16:16alone won't work so how do we do this
- 16:19now I need to generate another strategy
- 16:21and I can pick whichever name I like but
- 16:23I'm going to go with Paris trading two
- 16:28all right so I'm also going to open this
- 16:31one all right so now we're going to deal
- 16:34with two strategy files now I know you
- 16:36guys have some questions like how do we
- 16:38communicate between the two strategies
- 16:40how do we connect them to each other and
- 16:42I'm going to take care of the heavy
- 16:43lifting right now so let's connect these
- 16:45two strategies together so inside my
- 16:48first route I'm going to define the
- 16:51before function and in it I'm going to
- 16:53say if the current index is zero which
- 16:56means it's the beginning of the
- 16:57execution of the Strat
- 16:59I'm going to initiate two variables and
- 17:03I'm using this special dictionary
- 17:05variable inside Jesse called shared
- 17:07wordss now why is it called that it's
- 17:10called shared wordss as in whichever
- 17:11variable that you define in this
- 17:13dictionary is going to be shared among
- 17:16all the trading routes that you have and
- 17:17I'm calling the first one S1 position
- 17:20and I'm setting it to zero and then I
- 17:22Define another one for the second one
- 17:24and my shoot long is going to be very
- 17:27simple I'm going to say return true if
- 17:30the S1 position value equals one that's
- 17:32it and we're choosing one as in a long
- 17:35position so that means for a short
- 17:38position we need to do the opposite so
- 17:40that would be this right if the S1
- 17:43position equals minus1 next I will take
- 17:46care of closing these positions and
- 17:48that's going to be using the update
- 17:50position method and in it I'm going to
- 17:53say if the value of S1 position equals
- 17:55zero I'm going to use the self.
- 17:58liquidate method to liquidate the
- 18:00current position for this trading route
- 18:02next I'm going to go to the second
- 18:03strategy and inside this shoong I'm
- 18:06going to say return if the shared vs
- 18:10S2 position equals 1 and we're going to
- 18:13do the opposite for a short position and
- 18:15again be careful with the key here it
- 18:17needs to be S2 because we're inside the
- 18:19second strategy and then I'm going to
- 18:23define the update position and do the
- 18:26opposite of what I did for the first
- 18:28strategy so I'm saying if the S2
- 18:30position equals zero that means we need
- 18:32it to be closed so we will liquidate the
- 18:34current position right so next we have
- 18:37the position sizing so I'm going to back
- 18:39to the first route and inside the goong
- 18:42method I'm going to say this the
- 18:44quantity of my position is going to be
- 18:46the margin one which is this value that
- 18:49I'm going to Define for the the size of
- 18:52the position of the first position and
- 18:54I'm using this utility function called
- 18:56size to quantity which will take this as
- 18:59the first parameter and then the current
- 19:01price because I want to open the
- 19:03position with the market order and then
- 19:04I'm setting the trading fees and then
- 19:06all I need to do is to say self. buy
- 19:08equals quantity and then the current
- 19:10price to open a position using the
- 19:12current price and for the short position
- 19:14I'm going to do the opposite so again
- 19:17quantity equals
- 19:19this but instead of self. buy I'm
- 19:22passing self. sell equals quantity and
- 19:25then the current price all right so
- 19:27let's go to the second route
- 19:29and do the same thing here so I'm going
- 19:31to say Quantity equals this except that
- 19:35instead of margin one it needs to be
- 19:36margin two and then I will say s. buy
- 19:40equals quantity and then the current
- 19:41price and then for the go short position
- 19:45we'll do the same thing again ensure
- 19:47that this one is margin two and then
- 19:49instead of self. buy we have self. sell
- 19:52all right I don't know what you're
- 19:53thinking right now but if it's not clear
- 19:55yet don't worry cuz it's going to be in
- 19:57a second but all you need to know is
- 19:59that at this point these two strategy
- 20:01files are connected to each other so
- 20:04wherever we change these four variables
- 20:06the S1 position S2 position and S1
- 20:09margin and S2 margin is going to take
- 20:11effect everywhere but now we need to
- 20:13define the logic of our strategy the one
- 20:16we just implemented inside this Jupiter
- 20:18notebook inside our first strategy so in
- 20:21fact I'm not going to touch the second
- 20:23strategy file at all anymore I'm
- 20:25completely done with it but for the
- 20:26first one let's begin all right so let's
- 20:28let's go back to the Jupiter notebook
- 20:31and here we were getting the candles
- 20:33like this using the research module but
- 20:35if I do it like this during a back test
- 20:38there's a good chance I'm going to use
- 20:39data from the future and we don't want
- 20:42that right because that would produce
- 20:43unrealistic results so instead I want to
- 20:46use Jess's built-in features for fishing
- 20:48the candles which insures we don't
- 20:50accidentally cause the liad bias in our
- 20:52strategy all right so I'm going to go
- 20:54back to the first strategy and I will
- 20:56Define a new property called C1 and in
- 20:59it I'm going to pass self. getet candles
- 21:02which is that built-in method for
- 21:04fishing the candles and again this one
- 21:06in Short you don't fish candles from the
- 21:08future Jesse will take care of it behind
- 21:10the scenes to only give you candles that
- 21:12you had at that point in time and the
- 21:14first parameter is the exchange and
- 21:16we're passing the current exchange and
- 21:18then the symbol now this one it could
- 21:21have Simply Be ET us right but because I
- 21:25wanted to Define it dynamically instead
- 21:27I I can use this self. rout and then I'm
- 21:30selecting the index of zero and then I'm
- 21:33selecting its symbol so this way no
- 21:35matter in back testing whichever symbol
- 21:38I choose here it will work here and I
- 21:40don't have to change anything so it's
- 21:42better now I'm also doing the same thing
- 21:44for time frame so I'm passing self. time
- 21:46frame which will give it whichever time
- 21:48frame that I pick here so instead of
- 21:50simply saying 15 minutes I'm using self.
- 21:54time frame and because I want only the
- 21:57closing price I as I showed you earlier
- 21:59in the jupyter notebooks I'm selecting
- 22:02all of them but only the closing prices
- 22:04which has the index of two but I'm also
- 22:06selecting only the last 200 candles and
- 22:09why is that well in the jupyter notebook
- 22:11we only had candles for 2 days right but
- 22:15when we are back testing let's say we
- 22:17want to back test it on multiple months
- 22:18if you give it so much data the mean of
- 22:21this data series is going to change a
- 22:23lot and it's not going to even be
- 22:25remotely what we need it to be so I want
- 22:27to make sure that we we catch the
- 22:29pattern of only the most recent data and
- 22:32that could be the last 2 days 3 days
- 22:34whatever but the point is it has to be a
- 22:38static number and I chose 200 you can
- 22:41try any other number and see whichever
- 22:43works best for you all right so now
- 22:46let's define another one and call it C2
- 22:50which is going to be very similar except
- 22:52we're selecting the second route by
- 22:54using the index one and everything else
- 22:56is the rest so you see inside my first
- 22:59strategy file I have access to the data
- 23:02or everything from even the second
- 23:04strategy so that's why I said I'm not
- 23:06going to touch the second strategy file
- 23:08at all all right now let's define the
- 23:11zcore right so first we need the
- 23:15spread and that is going to be self. C1
- 23:19minus self. C2 and again we're selecting
- 23:22from the index of one until the end
- 23:25which again is what I just did inside
- 23:26the Jupiter notebook and then I'm we
- 23:28going to say zscore equals utils zscore
- 23:32and I'm passing the spread and in the
- 23:34end I'm returning zscore minus one which
- 23:37will give me the last item inside this
- 23:40array and that's going to be the only
- 23:41one that I care about cuz it's not like
- 23:43I want to paint a chart with it right
- 23:45right so where do we Define the logic of
- 23:46the strategy or the rest of it now
- 23:48everything else will happen inside the
- 23:51before function now by the way in case
- 23:53you didn't know the before function is
- 23:55the first method inside the strategy
- 23:57cycle of J that we get called so
- 24:00whichever value that we set inside the
- 24:03before function is going to be
- 24:04accessible inside everything else inside
- 24:07the shoot long the go long the update
- 24:09position everything so that's why I'm
- 24:11doing all the decision makings inside
- 24:13this one and then setting the decisions
- 24:15inside these variables and then I'm
- 24:17checking for the result of those
- 24:19variables like for example in here all
- 24:21right now let's continue so once every
- 24:2424 hours or one day I want to
- 24:26recalculate everything like I want to
- 24:28see if the pairs are still Co integrated
- 24:30or things like that so I'm going to say
- 24:32this if self index equals 0 which means
- 24:37in the beginning or if the remainder of
- 24:40self. index divided by one day worth of
- 24:44one minute candles and we can get that
- 24:46by saying 24 multiped by 60 divided by
- 24:51this number here right now what is this
- 24:53number because we're using the 15
- 24:55minutes this is basically 15 but as it
- 24:59was the case with whichever whatever I
- 25:02did here so instead of hard coding I was
- 25:04using Dynamic values so that if we
- 25:06change something inside the js's
- 25:08dashboard it will take effect here right
- 25:11so because of that instead of Simply
- 25:13dividing it by 15 I'm going to divide it
- 25:16by this value I'm using the utility
- 25:17module again and the function time frame
- 25:20to 1 minute and then I'm passing the
- 25:22current time frame which is 15 minutes
- 25:24and it is returning 15 now I'm saying if
- 25:27the remainder of this division is zero
- 25:30that means it has passed 24 hours then I
- 25:34want to check for qution is qug grated
- 25:37equals utils do R cointegrated and then
- 25:40I'm passing the first set of price
- 25:41returns and then I'm passing the second
- 25:43one and if they are not going integrated
- 25:45anymore I want to close all the
- 25:47positions and I can do that by setting
- 25:49both these values S1 position and S2
- 25:52position to zero all right now let's
- 25:54move on next we're going to define the
- 25:56zscore and we can simply get that using
- 25:59the self. Z score which we defined in
- 26:01here right so let's get that one now I'm
- 26:04going to say if the current position is
- 26:06closed and we can simply get that using
- 26:09this and the
- 26:11zcore is below the threshold that we
- 26:15Define in here you remember these two
- 26:17lines it was
- 26:201.2 and minus 1.2 so I'm going to use
- 26:22that here so if the zcore is below minus
- 26:271 2 then I'm going to say go long with
- 26:31the first position by simply setting it
- 26:33to one and go short the second position
- 26:37by simply setting it to minus one now
- 26:39next I'm going to say let's remove this
- 26:43next I'm going to say else if it is
- 26:45already long but the Z score is above
- 26:48zero now in other words so you remember
- 26:51this we went long here but once it
- 26:54reaches the mean we want to close the
- 26:55position so I'm going to say if the Z is
- 26:58is now above zero set this one to zero
- 27:02and also this one all right so both
- 27:04positions need to be zero or closed and
- 27:08next I'm going to say if it's a short
- 27:09position and the Z score is below zero
- 27:12and that would be this case so if we
- 27:14went short but the mean is now below the
- 27:17mean then again close both positions and
- 27:20lastly I'm going to say else if it is
- 27:22closed but the zcore is above 1.2 which
- 27:26would be this case I want to short the
- 27:29first position and long the second
- 27:31position all right now we have the
- 27:32decision- making of our strategy we know
- 27:34when exactly it's going to go long and
- 27:37when is going to go short however we're
- 27:39still missing one variable and that is
- 27:41the size of the position and this is
- 27:43really important because the bigger the
- 27:45size of the market cap of an asset the
- 27:47less volatile it will be so in our case
- 27:50we already know that the price of
- 27:52ethereum will move less than the price
- 27:54of ethereum classic so let's say they
- 27:56are moving exactly at the same time if
- 27:58only the size of the positions are
- 28:00exactly the same for example if we long
- 28:02one of them with $1,000 and short the
- 28:04other one with $1,000 when they move
- 28:07let's say they both go up it's still the
- 28:09one with the lower market cap which
- 28:10would be ethereum classic in this case
- 28:12and that means if it was the long
- 28:14position we're going to be in profit but
- 28:16if it was the short position we would
- 28:17lose money right and that's not what we
- 28:19want so we need to make sure the size of
- 28:21these positions are not exactly the same
- 28:23value but they are somehow equal in
- 28:26matter of like how much money money we
- 28:28would make or lose between them right
- 28:30now how do we do that so first I'm going
- 28:32to define a new function and I'm going
- 28:35to call it set proper margin per
- 28:39route all right and I'm going to call
- 28:43this firstly in here and second in here
- 28:48so again this is where we opened the
- 28:51first long position and the second short
- 28:53position and this is where we did the
- 28:55opposite right and these two were we
- 28:57were just closing an already open
- 28:59position now this is incorrect going to
- 29:01remove it now to calculate this I'm
- 29:04going to use a formula which again
- 29:06luckily Jesse provides us so we're going
- 29:08to get the alpha but I'm not going to
- 29:10use the alpha so I'm just going to pass
- 29:11an underline and then the beta and is
- 29:15going to equal utils do calculate Alpha
- 29:18Beta And this is this formula so we're
- 29:20using the assets model again right and
- 29:25this is the formula so the x equals add
- 29:27constant then we're passing the second
- 29:29returns and we're using a model to do
- 29:32linear regression I think and then that
- 29:34will give us the Alpha and the beta and
- 29:36then we are passing them I'm not going
- 29:38to go through the exact math behind it
- 29:40again if you want to just watch that
- 29:42video from quantopian which they do
- 29:44explain this better now this is giving
- 29:46us both the Alpha and the beta to
- 29:49calculate the margin I'm using the
- 29:52current available margin multiplied by 1
- 29:55ided by 1 + beta and for the second
- 29:59margin or the margin of the second
- 30:01position or the second strategy I'm
- 30:03using it like this now to be honest with
- 30:05you I'm not a math wizard myself and I
- 30:08use chat GPT heavily for writing this
- 30:10part but because I did a lot of testing
- 30:12I know it's actually working so sorry if
- 30:14I cannot explain this any better all
- 30:16right so that's it now we have the
- 30:18margin one the margin 2 and the values
- 30:20for S1 position and S2 position and now
- 30:23we're ready to execute our first
- 30:24practice so let's go back to Jesse and
- 30:28we have both the trading routes eth Etc
- 30:32the 15 minutes time frame P trading is
- 30:35selected but the second one also needs
- 30:37to be press rating two and the duration
- 30:41make sure the fast mode is off because
- 30:43it actually cannot work with multiple
- 30:45routes yet so if I try to start it here
- 30:47I'm going to get an error so let's turn
- 30:49this off and I'm going to leave the
- 30:52actually let's turn off The Benchmark
- 30:54first and let's run it all right so this
- 30:58result isn't right and I went back and
- 31:01found the issue the issue is that we are
- 31:03passing the current candles but as it
- 31:05was the case in here we later converted
- 31:08the current candles into price returns
- 31:10so we need to do the same thing in here
- 31:12so I'm going to select this and instead
- 31:15return prizes to returns and then pass
- 31:18this and this all right and I'm also
- 31:21going to do it here all right so again
- 31:24we are converting the current candles
- 31:25into price returns and and that's the
- 31:28correct format for the calculations that
- 31:30we did with zcore and everything else
- 31:32all right so let's go back and run this
- 31:34one more
- 31:35time there we go this Equity curve looks
- 31:38unbelievably good and is for the last 12
- 31:42months the profit was 69% the Maxon isus
- 31:485% the M rate is 53% the sharp is
- 31:522.94 and the calmer is
- 31:5513.77 all right so let's go back and
- 31:58turn on The Benchmark feature too and
- 32:00run it one more time so while that's
- 32:03going I want to quickly remind you guys
- 32:04that I recently added support for Apex
- 32:06Omni which is a DEX which means you will
- 32:08keep the custody of your funds and
- 32:10there's no kyc you just connect your
- 32:12metamask wallet and you're good to go if
- 32:14you want to get started with Apex please
- 32:15consider using our link which will give
- 32:17you trading fee discounts and you'll
- 32:19also be supporting making these videos
- 32:21all right so check this out while the
- 32:23price was going up we made money while
- 32:26the price was going down we made money
- 32:29when it was in a Range we also made
- 32:31money so that's why we call this
- 32:33strategy a market neutral strategy cuz
- 32:35no matter if it's going up or down or in
- 32:38range you're going to make money as long
- 32:40as the bet that these two prize assets
- 32:43are going to Great is true right so
- 32:45that's why it's really fantastic so guys
- 32:48this result is actually too good to be
- 32:50true so I'm just going to buy a Lambo
- 32:52and make videos about how rich I am all
- 32:53right see you in the next video but hold
- 32:55on a second there's a catch multiple
- 32:57love them you see unlike my other videos
- 33:00or back test that I run I actually
- 33:03disable the trading fees in this case
- 33:05that's why we are not paying any trading
- 33:07fees and this is really important
- 33:09because it is taking
- 33:137,818 trades over a year that's simply
- 33:17too many trades and it's not like we own
- 33:19the exchange or are friends with them we
- 33:21are going to have to pay for trading
- 33:23fees and we're not even in hedge fund
- 33:25because hedge funds and I'm guessing
- 33:27Edward torb two they paid very little
- 33:29fees because they had special contracts
- 33:31but we don't so if we set the trading
- 33:33fee to what it actually would be on
- 33:35bance features and run this one more
- 33:39time let's disable the Benchmark
- 33:42feature now the result actually looks
- 33:45awful so we started by 10,000 and we
- 33:48ended with
- 33:50$343 now why is this is because again
- 33:53we're taking too many trades and we are
- 33:54paying just too much in trading fees
- 33:56we're paying 11 $1,000 in trading fees
- 33:59now it actually gets worse in reality
- 34:02not only we would have to pay this much
- 34:03trading fees but we're also going to
- 34:05have slippage and because in this
- 34:07strategy at least at the current state
- 34:10of it we're even counting on trades with
- 34:12very small margin of profit so that
- 34:14means if there's going to be slippage
- 34:16which there will be the results will
- 34:18look even worse than this so to get the
- 34:20real estate results we need to set this
- 34:23to a higher number such as this or maybe
- 34:25this one so what does this mean it means
- 34:27that if you're a H fund you can probably
- 34:28already trade this if you can get some
- 34:30kind of special contract or trade it on
- 34:32an exchange that has very little fees
- 34:34but for most of us that's not the case
- 34:36so what we can do is to implement as
- 34:40many filters as possible to make sure
- 34:42that we only take the trades that are
- 34:44worth it now the other thing that we can
- 34:46do is to trade only assets that are more
- 34:49volatile for example mem coins we know
- 34:51they are correlated with each other but
- 34:53they move much more and that means our
- 34:55trades probably won't have as little
- 34:57profit margin which would make it worth
- 35:00it for us I'm going to share the source
- 35:01code of this strategy on a GitHub
- 35:03repository and link to it down in the
- 35:05description it's going to be your
- 35:06homework to keep doing research and
- 35:09implementing filters to improve the
- 35:11results of this strategy and make it
- 35:13actually production ready you can also
- 35:15try it on other markets with different
- 35:16trading assets and see if it works there
- 35:18or preferably with exchanges that have
- 35:20lower trading fees I would love to see
- 35:22you guys on our Discord and share with
- 35:24me your experience with this strategy
- 35:26and let me know what works for you and
- 35:28what doesn't so that hopefully we can
- 35:30improve it if many of you guys want me
- 35:32to make a follow-up video about this
- 35:33strategy I might do it so just let me
- 35:35know about it now as always we're going
- 35:37to have a giveaway the random person who
- 35:38likes this video posts a comment and
- 35:40subscribes to the channel is going to
- 35:42win 1 million bunk token all right let's
- 35:43pick the winner for the previous
- 35:46video and the winner is rames thank you
- 35:49so much for your comment please reach
- 35:50out to me so that I can send you your
- 35:52bunk tokens thanks for watching and I'll
- 35:53see you in the next one
- 35:56[Music]
- 35:58oh
- 36:01[Music]
About this transcript
This page contains the full transcript of Pairs-trading strategy from scratch in Python by Algo-trading with Saleh, generated from the public captions YouTube serves with the video. The transcript has 6,924 words across 911 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.
What you can do with it
Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.
Free YouTube transcript tool
YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.