• Keine Ergebnisse gefunden

3.2 Implementation in Go

3.2.6 Timing After First Optimisation in Go

After plugging in the optimisedrolling_maxinto the backtesting function, the timing has to evaluated anew. In the following Table 3.3 the timing results are enlisted.

Timing in Python and Go

Backtesting averaged in ms std. dev. in ms pct. pct. pct.

Python loop based 2742.3350 47.406406 100%

Python vectorised 23.7179 4.562519 0.86% 100%

Go serial 21.12 2.054707235 0.77% 89.05% 100%

Go opt. rolling max 14.172 1.246583319 0.52% 59.75% 67.10%

Table 3.3: Timing of the Python and Go implementation after the first optimisation

According to Table 3.3, the backtesting now only uses 59.75% of the running time used by the vectorised approach in Python which is an improvement by a factor of about 1.7×.

3.2.7 CPU Profiling of the First Optimisation in Go

Looking at the CPU profiling in Figure 3.2 after running the backtesting with the optimisedrolling_max function, it is observable that the portion of the execution time spent inmax_in_slicehas now reduced from 59.77%

to 36.88%. (A larger version of Figure 3.2 is available on2)

Subsequently, the optimisation steps described in Subsections 3.2.3 to 3.2.7 are repeated with all the other functions which use a lot of the execution time of the backtesting function.

3.2.8 Timing of BackTest_C2a_MAR

After very the time consuming optimisation of all time intensive functions, it is time to benchmark the entireBackTest_C2a_MAR function. The results thereof are enlisted in Table 3.4.

Timing in Python and Go

Backtesting averaged in ms std. dev. in ms pct. pct. pct.

Python loop based 2742.3350 47.406406 100%

Python vectorised 23.7179 4.562519 0.86% 100%

Go serial 21.12 2.054707235 0.77% 89.05% 100%

Go opt. rolling max 14.172 1.246583319 0.52% 59.75% 67.10%

Go concurrent 8.214 1.045608577 0.30% 34.63% 38.89%

Table 3.4: Timing of the Python and Go implementation after the optimisation

Table 3.4 shows that the concurrent backtesting in Go only takes 34.63% of the time of the vectorised version in Python which is a speed-up factor of 2.9×.

2https://battilanablog.files.wordpress.com/2017/11/cpuprofile02.pdf

When examining the profiling results of the fully optimisedBackTest_C2a_MAR in Figure 3.3, it is noticeable that the total duration came down from 14.93s to 9.22s. In addition, when looking at the rolling_max, the percentage of the total execution time rose from 36.88% to 37.33%, however, the time spent within it decreased from 9.96s to 8.34s. (A larger version of Figure 3.3 is available on3)

The complete and fully optimised code is available on4.

3.3 Outlook

The next step is the integration of the optimised function into Python, in other words, make the Go function directly callable from Python. This inte-gration is already in the working but, unfortunately, it could not be finished before the deadline of this thesis. I will continue working with the Chair to finish the integration in the near future. Additionally, I am planning on benchmarking my implemented helper functions against the gonum floats library5 for possible further optimisation of the backtesting function. Then, the research group of Professor Sornette’s could swap the old and time intensive backtesting function implemented in Python with the optimised function implemented in Go in order to profit from the speed-up without rewriting the entire Python codebase.

3https://battilanablog.files.wordpress.com/2017/11/cpuprofile03.pdf

4https://battilana.uk/bachelor-thesis/

5https://github.com/gonum/gonum/tree/master/floats

Type: cpu

Time: Nov 3, 2017 at 10:46am (CET) Duration: 14.93s, Total samples = 27.01s (180.96%) Showing nodes accounting for 26.04s, 96.41% of 27.01s total Dropped 91 nodes (cum <= 0.14s)

main

File: sabm_initial13_profiling Type: cpu

Time: Nov 5, 2017 at 3:58pm (CET) Duration: 9.22s, Total samples = 22.34s (242.32%) Showing nodes accounting for 21.74s, 97.31% of 22.34s total Dropped 74 nodes (cum <= 0.11s)

runtime

0.10s gcMarkDoneruntimemgc.go 0 of 0.24s (1.07%)

Conclusion

First, the loop based backtesting function in Python was translated to a na¨ıve loop based implementation in Go. Astoundingly, this na¨ıve loop based im-plementation is already as fast as the vectorised version of the backtesting function in Python. To be precise, it is even about two milliseconds faster.

After localising the most time consuming function using CPU profiling, the identified function was optimised, tested and benchmarked. Reiterating these steps, namely CPU profiling, optimisation, testing and benchmarking, an optimised version of the backtesting function was reached. This version runs 2.9× faster than the vectorised backtesting in Python, that is to say it only uses 34.63% of the vectorised version’s execution time.

However, there is still room for improvement of the backtesting function. For instance, the number of goroutines used in each function within the back-testing function could be tweaked further, such that it runs the fastest in its intended environment. This environments is likely a cluster with many more cores available than the machine used and described in Subsection 3.0.1 (i). Additionally, a timing test with randomly generated data should be conducted, instead of only using the historic data from the S&P 500 in-dex. Doing so, the speed up projected in this thesis could be confirmed.

Plus, introducing table based benchmarking could increase code readability immensely.

In summary, the implementation and optimisation of the backtesting func-tion in Go achieves a substantial speed-up.

Appendix

A.1 Glossary

Channel ’is a model for interprocess communication and synchro-nization via message passing. A message may be sent over a channel, and another process or thread is able to receive mes-sages sent over a channel it has a reference to, as a stream.

Different implementations of channels may be buffered or not, and either synchronous or asynchronous.’ [13]

Communicating Sequential Processes ’(CSP) is a formal language for describing patterns of interaction in concurrent systems.

It is [...] based on message passing via channels.’ [33]

Critical Section ’refers to an interval of time during which a thread of execution accesses a shared resource, such as shared mem-ory.’ [30]

Data Race confer race condition below.

False Sharing ’is a performance-degrading usage pattern that can arise in systems with distributed, coherent caches at the size of the smallest resource block managed by the caching mech-anism. When a system participant attempts to periodically access data that will never be altered by another party, but that data shares a cache block with data that is altered, the caching protocol may force the first participant to reload the whole unit despite a lack of logical necessity. The caching system is unaware of activity within this block and forces the first participant to bear the caching system overhead re-quired by true shared access of a resource.’ [36]

Functional programming ’is a programming paradigm [...] that treats computation as the evaluation of mathematical func-tions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means program-ming is done with expressions or declarations instead of statements. In functional code, the output value of a func-tion depends only on the arguments that are passed to the function, so calling a function f twice with the same value for an argument x produces the same result f(x) each time; this is in contrast to procedures depending on a local or global state, which may produce different results at different times when called with the same arguments but a different pro-gram state. Eliminating side effects, i.e., changes in state that do not depend on the function inputs, can make it much eas-ier to understand and predict the behavio[u]r of a program, which is one of the key motivations for the development of functional programming.’ [12]

Imperative programming ’is a programming paradigm that uses statements that change a program’s state. In much the same way that the imperative mood in natural languages expresses commands, an imperative program consists of commands for the computer to perform. Imperative programming fo-cuses on describing how a program operates.’ [11]

Interpreted language ’is a programming language for which most of its implementations execute instructions directly, without previously compiling a program into machine-language in-structions. The interpreter executes the program directly, translating each statement into a sequence of one or more subroutines already compiled into machine code.

The terms interpreted language and compiled language are not well defined because, in theory, any programming lan-guage can be either interpreted or compiled.’ [18]

Light-weight process (LWP) ’is a means of achieving multitask-ing. In the traditional meaning of the term [...] a LWP runs in user space on top of a single kernel thread and shares its address space and system resources with other LWPs within the same process.’ Sometimes LWP are also called user-level threads which are implemented directly on top of a kernel thread. [14]

Master/Worker ’(or sometimes also Master/slave) is a model of communication where one device or process has unidirec-tional control over one or more other devices. In some

sys-tems a master is selected from a group of eligible devices, with the other devices acting in the role of slaves.’ [35]

Multiplexer ’is a device that selects one of several analog or digi-tal input signals and forwards the selected input into a single line.’ [30]

Mutual Exclusion (also Mutex) ’is a property of concurrency con-trol, which is instituted for the purpose of preventing race conditions+; it is the requirement that one thread of execu-tion never enter its critical secexecu-tion+ at the same time that another concurrent thread of execution enters its own criti-cal section+.’ [30]

Object-oriented programming ’(OOP) is a programming paradigm based on the concept of ”objects”, which may contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods. A feature of objects is that an object’s procedures can access and often modify the data fields of the object with which they are asso-ciated (objects have a notion of ”this” or ”self”). [...] There is significant diversity of OOP languages, but the most pop-ular ones are class-based, meaning that objects are instances of classes, which typically also determine their type.’ [9]

Procedural programming ’is a programming paradigm [...] based upon the concept of the procedure call. Procedures, also known as routines, subroutines, or functions [...], [which]

simply contain a series of computational steps to be carried out. Any given procedure might be called at any point dur-ing a program’s execution, includdur-ing by other procedures or itself. [...] Procedural programming languages are also im-perative languages’. Examples of procedural programming languages are C and Go. [10]

Race Condition (sometimes called data race) ’is the behaviour of an electronic, software, or other system where the output is dependent on the sequence or timing of other uncontrollable events. It becomes a bug when events do not happen in the order the programmer intended. The term originates with the idea of two signals racing each other to influence the output first.’ [31]

Semaphore ’is a variable or abstract data type used to control access to a common resource by multiple processes in a con-current system such as a multiprogramming operating sys-tem.’ [40]

Slices ’Go’s slice type provides a convenient and efficient means of working with sequences of typed data. Slices are analo-gous to arrays in other languages [...]’ [37]

S&P 500 ’The Standard & Poor’s 500, often abbreviated as the S&P 500, or just the S&P, is an American stock market index based on the market capitalisations of 500 large companies having common stock listed on the NYSE or NASDAQ.’ [38]

A.2 Listings of Chapter 2 Methodology

Listing A.1: CPU profiling

1 p a c k a g e m a i n

2

3 i m p o r t (

4 ...

5 " f l a g " // p r o f i l i n g

6 " r u n t i m e / p p r o f " // p r o f i l i n g

7 )

8

9 // f u n c t i o n s up h e r e

10 ...

11

12 / / # # # # # # # # # # # # # # # P R O F I L I N G # # # # # # # # # # # # # # # #

13 var c p u p r o f i l e = f l a g . S t r i n g (" c p u p r o f i l e " , "" , " w r i t e cpu p r o f i l e to f i l e ")

14 / / # # # # # # # # # # # # # # # P R O F I L I N G end # # # # # # # # # # # #

15

16 f u n c m a i n () {

17 / / # # # # # # # # # # # # P R O F I L I N G # # # # # # # # # # # # # # #

18 f l a g . P a r s e ()

19 if * c p u p r o f i l e != "" {

20 f , err := os . C r e a t e (* c p u p r o f i l e )

21 if err != nil {

22 log . F a t a l (" c o u l d not c r e a t e CPU p r o f i l e : " , err )

23 }

24 if err := p p r o f . S t a r t C P U P r o f i l e ( f ) ; err != nil {

25 log . F a t a l (" c o u l d not s t a r t CPU p r o f i l e : " , err )

26 }

27 d e f e r p p r o f . S t o p C P U P r o f i l e ()

28 }

29 / / # # # # # # # # # # # # P R O F I L I N G end # # # # # # # # # # #

30 ...

31 // c o d e h e r e

32 ...

33 }

Listing A.2: Example of a benchmark template

1 p a c k a g e m a i n

2

3 i m p o r t (

4 " t e s t i n g "

5 " fmt "

6 )

7

8 // s o m e t y p e d e c l a r a t i o n for f u n c t i o n for b r e v i t y

9 ...

10 11

12 / / # # # # # # # # # # # B E N C H M A R K T E M P L A T E S # # # # # # # # # # #

13 // as a b o v e but for u n a r y f u n c t i o n s

14 var res _ s e r i a l _ u n a r y _ s l i c e [] f l o a t 64

15 f u n c b e n c h m a r k _ s e r i a l _ u n a r y _ s l i c e ( b * t e s t i n g . B , i n p u t [] f l o a t 64 , fn s e r i a l _ u n a r y _ s l i c e ) {

16 var r [] f l o a t 64

17 for n := 0; n < b . N ; n ++ {

18 r = fn ( i n p u t )

19 }

20 res _ s e r i a l _ u n a r y _ s l i c e = r

21 }

22 // as a b o v e but for b i n a r y f u n c t i o n s

23 var res _ c o n c u r r e n t _ b i n a r y _ s l i c e [] f l o a t 64

24 f u n c b e n c h m a r k _ c o n c u r r e n t _ b i n a r y _ s l i c e ( b * t e s t i n g . B , num _ g o r o u t i n e s int , i n p u t [] f l o a t 64 , fn c o n c u r r e n t _ b i n a r y _ s l i c e ) {

25 var r [] f l o a t 64

26 for n := 0; n < b . N ; n ++ {

27 r = fn ( input , num _ g o r o u t i n e s )

28 }

29 res _ c o n c u r r e n t _ b i n a r y _ s l i c e = r

30 }

31 / / # # # # # # # # # B E N C H M A R K T E M P L A T E S end # # # # # # # # #

Listing A.3: Example of a benchmark file containing benchmarks functions

1 p a c k a g e m a i n

2

3 i m p o r t (

4 " t e s t i n g "

5 )

6

7 / / # # # # # # # # # # # # # # # B E N C H M A R K S # # # # # # # # # # # # # # #

8 f u n c B e n c h m a r k A n n u a l V o l F r o m D a i l y R e t u r n s _ s e r i a l ( b * t e s t i n g . B ) {

9 b e n c h m a r k _ s e r i a l _ u n a r y _ s l i c e ( b , returns , a n n u a l V o l F r o m D a i l y R e t u r n s )

10 }

11 f u n c B e n c h m a r k A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t _1(

b * t e s t i n g . B ) {

12 b e n c h m a r k _ c o n c u r r e n t _ b i n a r y _ s l i c e ( b , 1 , returns , a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t )

13 }

14 f u n c B e n c h m a r k A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t _4(

b * t e s t i n g . B ) {

15 b e n c h m a r k _ c o n c u r r e n t _ b i n a r y _ s l i c e ( b , 4 , returns , a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t )

16 }

17 f u n c B e n c h m a r k A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t _8(

b * t e s t i n g . B ) {

18 b e n c h m a r k _ c o n c u r r e n t _ b i n a r y _ s l i c e ( b , 8 , returns , a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t )

19 }

20 f u n c B e n c h m a r k A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t _ 3 2 ( b * t e s t i n g . B ) {

21 b e n c h m a r k _ c o n c u r r e n t _ b i n a r y _ s l i c e ( b , 32 , returns , a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t )

22 / / # # # # # # # # # # # # # # # B E N C H M A R K S end # # # # # # # # # # #

Listing A.4: Example of a test template

1 p a c k a g e m a i n

2

3 i m p o r t (

4 " t e s t i n g "

5 " fmt "

6 )

7

8 // s o m e t y p e d e c l a r a t i o n for f u n c t i o n for b r e v i t y

9 ...

10 11

12 / / # # # # # # # # # # # # # T E S T T E M P L A T E S # # # # # # # # # # # # # #

13 // as a b o v e but now t e s t i n g a c o n c u r r e n t f u n c t i o n w i t h b i n a r y i n p u t w h i c h r e t u r n s a s l i c e for c o r r e c t n e s s

14 f u n c t e s t _ s e r i a l _ c o n c u r r e n t _ b i n a r y _ s l i c e ( t * t e s t i n g . T , i n p u t [] f l o a t 64 , num _ g o r o u t i n e s int , fn _ s e r i a l s e r i a l _ u n a r y _ slice , fn _ c o n c u r r e n t c o n c u r r e n t _ b i n a r y _ s l i c e ) {

15 var fw _ serial , fw _ c o n c u r r e n t , sw _ serial , sw _ c o n c u r r e n t [] f l o a t 64

16 fw _ s e r i a l = fn _ s e r i a l ( r e t u r n s )

17 sw _ s e r i a l = fn _ s e r i a l ( r e t u r n s )

18 fw _ c o n c u r r e n t = fn _ c o n c u r r e n t ( returns , num _ g o r o u t i n e s )

19 sw _ c o n c u r r e n t = fn _ c o n c u r r e n t ( returns , num _ g o r o u t i n e s )

20

21 if ! is _ e q u a l ( fw _ serial , fw _ c o n c u r r e n t , a c c u r a c y _ b e n c h ) {

22 fmt . P r i n t f (" s e r i a l c o n c u r r e n t : fw _ s e r i a l : %v fw concurrent: t.Errorf("serial concurrent: fw serial not equal fw concurrent!")

23 }

24 if ! is _ e q u a l ( sw _ serial , sw _ c o n c u r r e n t , a c c u r a c y _ b e n c h ) {

25 fmt . P r i n t f (" s e r i a l c o n c u r r e n t : sw _ s e r i a l : %v



sw concurrent: t.Errorf("serial concurrent: sw serial not equal sw concurrent!")

26 }

27 }

28 / / # # # # # # # # # # # # # T E S T T E M P L A T E S end # # # # # # # # # #

Listing A.5: Example of a benchmark file containing test functions

1 p a c k a g e m a i n

2

3 i m p o r t (

4 " t e s t i n g "

5 )

6

7 / / # # # # # # # # # # # # # # # T E S T S # # # # # # # # # # # # # # # # # # # #

8 f u n c T e s t A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t ( t * t e s t i n g . T ) {

9 t e s t _ s e r i a l _ c o n c u r r e n t _ b i n a r y _ s l i c e ( t , returns , 4 , a n n u a l V o l F r o m D a i l y R e t u r n s ,

a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t )

10 }

11 f u n c T e s t A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t 11( t * t e s t i n g . T ) {

12 t e s t _ s e r i a l _ c o n c u r r e n t _ b i n a r y _ s l i c e ( t , returns , 4 , a n n u a l V o l F r o m D a i l y R e t u r n s ,

a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t 11)

13 }

14 f u n c T e s t A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t 2( t * t e s t i n g . T ) {

15 t e s t _ s e r i a l _ c o n c u r r e n t _ b i n a r y _ s l i c e ( t , returns , 4 , a n n u a l V o l F r o m D a i l y R e t u r n s ,

a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t 2)

16 }

17 f u n c T e s t A n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t 3( t * t e s t i n g . T ) {

18 t e s t _ s e r i a l _ c o n c u r r e n t _ b i n a r y _ s l i c e ( t , returns , 4 , a n n u a l V o l F r o m D a i l y R e t u r n s ,

a n n u a l V o l F r o m D a i l y R e t u r n s _ c o n c u r r e n t 3)

19 }

20 / / # # # # # # # # # # # # # # # T E S T S end # # # # # # # # # # # # # # # #

Listing A.6: Concurrent rolling max admitting possible false sharing

1 f u n c r o l l i n g _ max _ c o n c u r r e n t ( i n p u t [] f l o a t 64 , w i n d o w _ size , num _ g o r o u t i n e s int ) [] f l o a t 64 {

2 var o u t p u t = m a k e ([] f l o a t 64 , len ( i n p u t ) )

3 if len ( i n p u t ) > 0 {

4 num _ i t e m s := len ( i n p u t ) - ( w i n d o w _ s i z e - 1)

5 var b a r r i e r _ wg s y n c . W a i t G r o u p

6 n := num _ i t e m s / num _ g o r o u t i n e s

7

8 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

9 b a r r i e r _ wg . Add (1)

10 go f u n c ( go _ id int ) {

11 d e f e r b a r r i e r _ wg . D o n e ()

12

13 // c o m p u t i n g b o u n d a r i e s

14 var start , s t o p int

15 s t a r t = go _ id * int ( n ) + ( w i n d o w _ s i z e - 1) //

s t a r t i n g i n d e x

16 // e n d i n g i n d e x

17 if go _ id != ( num _ g o r o u t i n e s - 1) {

18 s t o p = s t a r t + n // E n d i n g i n d e x

19 } e l s e {

20 s t o p = num _ i t e m s + ( w i n d o w _ s i z e - 1) //

E n d i n g i n d e x

21 }

22

23 for i := s t a r t ; i < s t o p ; i ++ {

24 o u t p u t [ i ] = max _ in _ s l i c e ( i n p u t [ i -( w i n d o w _ size -1) : i + 1 ] )

25 }

26 }( i )

27 }

28 b a r r i e r _ wg . W a i t ()

29

30 } e l s e { // e m p t y i n p u t

31 fmt . P r i n t l n (" r o l l i n g _ max is p a n i c k i n g !")

32 p a n i c ( fmt . S p r i n t f ("%v", input))

33 }

34 r e t u r n o u t p u t

35 }

Listing A.7: Concurrent rolling max avoiding false sharing

1 f u n c r o l l i n g _ max _ c o n c u r r e n t _ n o F a l s e S h a r i n g ( i n p u t []

f l o a t 64 , w i n d o w _ size , num _ g o r o u t i n e s int ) [] f l o a t 64 {

2 var o u t p u t = m a k e ([] f l o a t 64 , w i n d o w _ size -1 , len ( i n p u t ) )

3 if len ( i n p u t ) > 0 {

4 num _ i t e m s := len ( i n p u t ) - ( w i n d o w _ s i z e - 1)

5 var b a r r i e r _ wg s y n c . W a i t G r o u p

6 n := num _ i t e m s / num _ g o r o u t i n e s

7 go _ max := m a k e ( [ ] [ ] f l o a t 64 , num _ g o r o u t i n e s )

8 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

9 go _ max [ i ] = m a k e ([] f l o a t 64 , 0 , num _ g o r o u t i n e s )

10 }

11 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

12 b a r r i e r _ wg . Add (1)

13 go f u n c ( go _ id int ) {

14 d e f e r b a r r i e r _ wg . D o n e ()

15

16 // c o m p u t i n g b o u n d a r i e s

17 var start , s t o p int

18 s t a r t = go _ id * int ( n ) + ( w i n d o w _ s i z e - 1) //

s t a r t i n g i n d e x

19 // e n d i n g i n d e x

20 if go _ id != ( num _ g o r o u t i n e s - 1) {

21 s t o p = s t a r t + n // E n d i n g i n d e x

22 } e l s e {

23 s t o p = num _ i t e m s + ( w i n d o w _ s i z e - 1) //

E n d i n g i n d e x

24 }

25

26 loc _ max := m a k e ([] f l o a t 64 , stop - s t a r t )

27 idx := 0

28 for i := s t a r t ; i < s t o p ; i ++ {

29 loc _ max [ idx ] = max _ in _ s l i c e ( i n p u t [ i -( w i n d o w _ size -1) : i + 1 ] )

30 idx ++

31 }

32 go _ max [ go _ id ] = a p p e n d ( go _ max [ go _ id ] , loc _ max . . . )

33

34 }( i )

35 }

36 b a r r i e r _ wg . W a i t ()

37

38 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

39 o u t p u t = a p p e n d ( output , go _ max [ i ] . . . )

40 }

41

42 } e l s e { // e m p t y i n p u t

43 fmt . P r i n t l n (" r o l l i n g _ max is p a n i c k i n g !")

44 p a n i c ( fmt . S p r i n t f ("%v", input))

45 }

46 r e t u r n o u t p u t

47 }

Listing A.8: Concurrent rolling max function using the master worker paradigm during optimi-sation attempt using the elements from [8]

1 f u n c W o r k e r ( in c h a n * Work , out c h a n * W o r k ) {

2 for {

3 t := < - in

4 t . Fn ( t . input , t . output , t . start , t . end )

5 t . C o m p l e t e d = t r u e

6 out < - t

7 }

8 }

9

10 f u n c c o m p u t e _ w i n d o w _ max ( input , o u t p u t [] f l o a t 64 , start , end int ) {

11 o u t p u t [ end -1] = max _ in _ s l i c e ( i n p u t [ s t a r t : end ])

12 }

13

14 f u n c r o l l i n g _ max _ c o n c u r r e n t ( i n p u t [] f l o a t 64 , w i n d o w _ size , num _ g o r o u t i n e s int ) [] f l o a t 64 {

15 var o u t p u t = m a k e ([] f l o a t 64 , len ( i n p u t ) )

16 if len ( i n p u t ) > 0 {

17 l e n g t h := len ( i n p u t )

18 num _ i t e m s := l e n g t h - ( w i n d o w _ s i z e - 1)

19 p e n d i n g := m a k e ( c h a n * W o r k )

20 d o n e := m a k e ( c h a n * W o r k )

21

22 // l o a d p e n d i n g w i t h w o r k

23 go f u n c () {

24 for i :=( w i n d o w _ s i z e - 1) ; i < l e n g t h ; i ++ {

25 p e n d i n g < - N e w W o r k ( c o m p u t e _ w i n d o w _ max , input , output , i -( w i n d o w _ size -1) , i +1)

26 }

27 }()

28

29 // s t a r t w o r k e r s

30 for i : = 0 ; i < num _ g o r o u t i n e s ; i ++ {

31 go f u n c () {

32 W o r k e r ( pending , d o n e )

33 }()

34 }

35

36 // w a i t t i l l all w o r k is d o n e

37 for i :=( w i n d o w _ s i z e - 1) ; i < num _ i t e m s ; i ++ {

38 < - d o n e

39 }

40

41 } e l s e { // e m p t y i n p u t

42 fmt . P r i n t l n (" r o l l i n g _ max is p a n i c k i n g !")

43 p a n i c ( fmt . S p r i n t f ("%v", input))

44 }

45 r e t u r n o u t p u t

46 }

A.3 Listings of Chapter 3 Experiments

Listing A.9: Loop based backtesting implementation in Python

1 def B a c k T e s t _ C 2 a _ MAR ( fw , sw , entry , exit , pexit , lexit , price , r e t u r n s ) :

2 c o m m i s s i o n R a t e = 0 . 0 0 2 5

3 f a s t M A = pd . r o l l i n g _ m e a n ( price , fw )

4 s l o w M A = pd . r o l l i n g _ m e a n ( price , sw )

5 i n d i c a t o r = f a s t M A / s l o w M A # MAR

6

7 p r i c e = p r i c e [ " 1 9 8 0 " : ]

8 r e t u r n s = r e t u r n s [ " 1 9 8 0 " : ]

9 i n d i c a t o r = i n d i c a t o r [ " 1 9 8 0 " : ]

10

11 t i m e L e n = len ( p r i c e )

12 t r a d i n g R e t u r n s = pd . S e r i e s (0.0 , i n d e x = p r i c e . i n d e x )

13 t r a d i n g p n l s = pd . S e r i e s (0.0 , i n d e x = p r i c e . i n d e x )

14 p n l C u r r e n t H o l d = pd . S e r i e s ( i n d e x = p r i c e . i n d e x )

15 t r a d i n g S t a t e s = pd . S e r i e s (0.0 , i n d e x = p r i c e . i n d e x )

16 t r a d i n g S t a t e _ t 0 = " I D L E "

17 t r a d i n g S t a t e _ t 1 = " I D L E "

18

19 h o l d S t a r t T i m e = -1

20 # 4 A v a i l a b l e States , IDLE , TO _ ENTER , HOLD , TO _ E X I T

21 for i in r a n g e (1 , t i m e L e n ) :

22 if t r a d i n g S t a t e _ t 0 == " I D L E ":

23 if ( i n d i c a t o r . i l o c [ i ] > e n t r y and

i n d i c a t o r . i l o c [ i -1] < e n t r y ) : # w h e n MAR g o e s t h r o u g h e n t r y _ t h r e s h o l d f r o m b e l o w

24 t r a d i n g S t a t e _ t 1 = " TO _ E N T E R " # U p d a t e the s t a t e for the n e x t t i m e s t e p t +1

25 t r a d i n g R e t u r n s . i l o c [ i ] =

-c o m m i s s i o n R a t e # C o m m i s s i o n Fee is p a i d at t 0

26

27 if t r a d i n g S t a t e _ t 0 == " TO _ E N T E R ":

28 h o l d S t a r t T i m e = i

29 t r a d i n g S t a t e _ t 1 = " H O L D "

30 t r a d i n g R e t u r n s . i l o c [ i ] = r e t u r n s . i l o c [ i ]

31 t r a d i n g S t a t e s . i l o c [ i ] = 1.0

32

33 if t r a d i n g S t a t e _ t 0 == " H O L D ":

34 t r a d i n g R e t u r n s . i l o c [ i ] = r e t u r n s . i l o c [ i ]

35 t r a d i n g S t a t e s . i l o c [ i ] = 1.0

36 p n l C u r r e n t H o l d . i l o c [ i ] = ( p r i c e . i l o c [ i ] -p r i c e . i l o c [ h o l d S t a r t T i m e ]) / -p r i c e . i l o c [ h o l d S t a r t T i m e ] + 1

37

38 if ( i n d i c a t o r . i l o c [ i ] < e x i t and i n d i c a t o r . i l o c [ i -1] > e x i t ) or p n l C u r r e n t H o l d . i l o c [ i ] < l e x i t or p n l C u r r e n t H o l d . i l o c [ i ] > p e x i t :

39 # w h e n MAR g o e r t h r o u g h e x i t _

t h r e s h o l d f r o m above , or w h e n s t o p P r o f i t , s t o p L o s s r e a c h e d

40 t r a d i n g S t a t e _ t 1 = " TO _ E X I T "

41 t r a d i n g R e t u r n s . i l o c [ i ] = r e t u r n s . i l o c [ i ] - c o m m i s s i o n R a t e

42 # C o m m i s s i o n Fee is p a i d at t 0 , a l s o

n e e d to i n c l u d e r e t u r n s at t 0 , s i n c e a g e n t e x i t m a r k e t at t 1

43

44 if t r a d i n g S t a t e _ t 0 == " TO _ E X I T ":

45 t r a d i n g S t a t e _ t 1 = " I D L E "

46 47 48

49 t r a d i n g S t a t e _ t 0 = t r a d i n g S t a t e _ t 1 # U p d a t e

50 51

52 res = pd . D a t a F r a m e ( i n d e x = p r i c e . i n d e x )

53 res [" T r a d i n g R e t u r n s "] = t r a d i n g R e t u r n s

54 res [" T r a d i n g S t a t e s "] = t r a d i n g S t a t e s

55 res [" T r a d i n g P N L s "] = p n l s F r o m R e t u r n s ( t r a d i n g R e t u r n s )

56 res [" T r a d i n g D r a w D o w n s "] = d r a w d o w n s F r o m P n l s ( res [" T r a d i n g P N L s "])

57 res [" H o l d P N L s "] = p n l C u r r e n t H o l d

58 59 60 61 62

63 # # # # # # # # # # # # # # # # # # # back - t e s t i n g r e s u l t for d i f f e r e n t back - t e s t i n g l e n g t h # # # # # # # # # #

64 # # # # # T h i s p a r t is v e c t o r i z e d # # # # # # # # # #

65 b t L e n N a m e s = [ " 1 0 y " , "5 y " , "2 y " , "1 y " , "6 m " , "3 m

"]

66 b t L e n s = [ 2 6 1 * 10 , 261 * 5 , 261 * 2 , 261 * 1 , 130 , 65 ]

67 b t L e n s I n Y e a r = [10.0 , 5.0 , 2.0 , 1.0 , 0.5 , 0 . 2 5 ]

68 # back - t e s t i n g w i n d o w lengths , 10 y , 5 y , 2 y , 1 y , 6 m ,3 m

69 70

71 for i in r a n g e (0 , len ( b t L e n s ) ) :

72 b t L e n N a m e = b t L e n N a m e s [ i ]

73 b t L e n = b t L e n s [ i ]

74 b t L e n I n Y e a r = b t L e n s I n Y e a r [ i ]

75 # A n n u a l i z e d R e t u r n s

76 res [" T r a d i n g A n n u a l i z e d R e t u r n s " + b t L e n N a m e ] = ( res [" T r a d i n g P N L s "]. pct _ c h a n g e ( b t L e n ) . add ( 1 . 0 ) ** ( 1 . 0 / b t L e n I n Y e a r ) - 1.0 )

77

78 for i in r a n g e (0 , len ( b t L e n s ) ) :

79 b t L e n N a m e = b t L e n N a m e s [ i ]

80 b t L e n = b t L e n s [ i ]

81 b t L e n I n Y e a r = b t L e n s I n Y e a r [ i ]

82 # M a x D r a w D o w n s

83 # b t L e n = S i z e of the m o v i n g w i n d o w

84 res [" T r a d i n g T r a i l i n g M a x D r a w D o w n " +

b t L e n N a m e ] = pd . r o l l i n g _ max ( res [" T r a d i n g D r a w D o w n s "] , b t L e n )

85 86

87 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

88 res [" f a s t M A "] = f a s t M A

89 res [" s l o w M A "] = s l o w M A

90 res [" I n d i c a t o r "] = i n d i c a t o r

91 r e t u r n res

Listing A.10: Vectorised backtesting implementation in Python

1 # V E C T O R I Z A T I O N W I T H P A N D A S

2 def B a c k T e s t _ C 2 a _ MAR _ vec ( fw , sw , entry , exit , pexit , lexit , price , r e t u r n s ) :

3 # V e c t o r i z e d P a n d a s

4 # s t o p L o s s and s t o p P r o f i t are not c o n s i d e r e d at c u r r e n t m o m e n t

5

6 f a s t M A = pd . r o l l i n g _ m e a n ( price , fw )

7 s l o w M A = pd . r o l l i n g _ m e a n ( price , sw )

8 i n d i c a t o r = f a s t M A / s l o w M A # MAR

9

10 p r i c e = p r i c e [ " 1 9 8 0 " : ]

11 r e t u r n s = r e t u r n s [ " 1 9 8 0 " : ]

12 i n d i c a t o r = i n d i c a t o r [ " 1 9 8 0 " : ]

13

14 i n d i c a t o r S h i f t = i n d i c a t o r . s h i f t (1) # s h i f t the row / c o l u m n by one

15

16 # s o m e e x p l a n a t i o n w o u l d be n i c e ...

17 t r a d i n g S i g n a l = pd . S e r i e s ( i n d e x = p r i c e . i n d e x )

18 t r a d i n g S i g n a l [( i n d i c a t o r >= e n t r y ) & ( i n d i c a t o r S h i f t < e n t r y ) ] = 1 # ... ?

19 t r a d i n g S i g n a l [( i n d i c a t o r <= e x i t ) & (

i n d i c a t o r S h i f t > e x i t ) ] = -1 # TO _ E X I T ?

20 t r a d i n g S i g n a l = t r a d i n g S i g n a l . d r o p n a () . d i f f () / 2.0

21 t r a d i n g S i g n a l = t r a d i n g S i g n a l [ t r a d i n g S i g n a l != 0]

22 t r a d i n g S i g n a l = t r a d i n g S i g n a l . f i l l n a ( 1 . 0 )

23

24 t r a d i n g S t a t e s = pd . S e r i e s ( i n d e x = p r i c e . i n d e x )

25 t r a d i n g S t a t e s [ t r a d i n g S i g n a l . i n d e x ] = t r a d i n g S i g n a l

26 t r a d i n g S t a t e s N o t F i l l e d = t r a d i n g S t a t e s . c o p y () # t h i s guy w i l l be n e e d e d for a d d i n g c o m m i s s i o n fee to r e t u r n s e r i e s

27 t r a d i n g S t a t e s = t r a d i n g S t a t e s . s h i f t (1) . f f i l l () # W h e n a S i g n a l Occurs , T r a d i n g is l a g g e d by one

t i m e s t e p

28 t r a d i n g S t a t e s [ t r a d i n g S t a t e s == -1] = 0

29 t r a d i n g S t a t e s = t r a d i n g S t a t e s . f i l l n a (0)

30

31 t r a d i n g R e t u r n s = pd . S e r i e s ( i n d e x = p r i c e . i n d e x )

32 t r a d i n g R e t u r n s [ t r a d i n g S t a t e s == 1] = r e t u r n s

33 t r a d i n g R e t u r n s [ t r a d i n g S t a t e s N o t F i l l e d == 1] = -c o m m i s s i o n R a t e

34 t r a d i n g R e t u r n s [ t r a d i n g S t a t e s N o t F i l l e d == 1] = -c o m m i s s i o n R a t e + r e t u r n s

35 t r a d i n g R e t u r n s = t r a d i n g R e t u r n s . f i l l n a (0)

36 37

38 res = pd . D a t a F r a m e ( i n d e x = p r i c e . i n d e x )

39 res [" T r a d i n g R e t u r n s "] = t r a d i n g R e t u r n s

40 res [" T r a d i n g S t a t e s "] = t r a d i n g S t a t e s

41 res [" T r a d i n g P N L s "] = ( t r a d i n g R e t u r n s + 1) . c u m p r o d ()

42 res [" T r a d i n g D r a w D o w n s "] = 1 - res [" T r a d i n g P N L s

"]. div ( res [" T r a d i n g P N L s "]. c u m m a x () )

43 res [" H o l d P N L s "] = p n l C u r r e n t H o l d

44

45 # # # # # # # # # # # # # # # # # # # back - t e s t i n g r e s u l t for d i f f e r e n t back - t e s t i n g l e n g t h # # # # # # # # # #

46 # # # # # T h i s p a r t is v e c t o r i z e d # # # # # # # # # #

47 b t L e n N a m e s = [ " 1 0 y " , "5 y " , "2 y " , "1 y " , "6 m " , "3 m

"]

48 b t L e n s = [ 2 6 1 * 10 , 261 * 5 , 261 * 2 , 261 * 1 , 130 , 65 ]

49 b t L e n s I n Y e a r = [10.0 , 5.0 , 2.0 , 1.0 , 0.5 , 0 . 2 5 ]

50 # back - t e s t i n g w i n d o w lengths , 10 y , 5 y , 2 y , 1 y , 6 m ,3 m

51 52

53 for i in r a n g e (0 , len ( b t L e n s ) ) :

54 b t L e n N a m e = b t L e n N a m e s [ i ]

55 b t L e n = b t L e n s [ i ]

56 b t L e n I n Y e a r = b t L e n s I n Y e a r [ i ]

57 # A n n u a l i z e d R e t u r n s

58 res [" T r a d i n g A n n u a l i z e d R e t u r n s " + b t L e n N a m e ] = ( res [" T r a d i n g P N L s "]. pct _ c h a n g e ( b t L e n ) . add ( 1 . 0 ) ** ( 1 . 0 / b t L e n I n Y e a r ) - 1.0 )

59

60 for i in r a n g e (0 , len ( b t L e n s ) ) :

61 b t L e n N a m e = b t L e n N a m e s [ i ]

62 b t L e n = b t L e n s [ i ]

63 b t L e n I n Y e a r = b t L e n s I n Y e a r [ i ]

64 # M a x D r a w D o w n s

65 res [" T r a d i n g T r a i l i n g M a x D r a w D o w n " +

b t L e n N a m e ] = pd . r o l l i n g _ max ( res [" T r a d i n g D r a w D o w n s "] , b t L e n )

66 67

68 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

69 r e t u r n res

Listing A.11: Backtesting timing implementation

1 # # # # # # # # # # b a c k g t e s t i n g l o o p b a s e d # # # # # # # # # #

2 t i m e _ l o o p _ ms = []

3 for i in r a n g e (0 ,10) :

4 t 0 0 0 0 = t i m e . t i m e ()

5 res 0 = B a c k T e s t _ C 2 a _ MAR ( fw , sw , entry , exit , pexit , lexit , price , r e t u r n s )

6 t 0 0 0 1 = t i m e . t i m e ()

7 t i m e _ l o o p _ ms . a p p e n d (( t 0001 - t 0 0 0 0 ) * 1 0 0 0 )

8 p r i n t ("%1.0f, loop based: print("averaged timing backtesting loop based:

9

10 # # # # # # # # # # b a c k g t e s t i n g vec # # # # # # # # # #

11 t i m e _ vec _ ms = []

12 for i in r a n g e (0 ,10) :

13 t 0 0 0 0 = t i m e . t i m e ()

14 res 1 = B a c k T e s t _ C 2 a _ MAR _ vec ( fw , sw , entry , exit , pexit , lexit , price , r e t u r n s )

15 t 0 0 0 1 = t i m e . t i m e ()

16 t i m e _ vec _ ms . a p p e n d (( t 0001 - t 0 0 0 0 ) * 1 0 0 0 )

17 p r i n t ("%1.0f, vec based: print("averaged timing backtesting loop based:

Listing A.12: Concurrent rolling max with no false sharing

1 f u n c r o l l i n g _ max _ c o n c u r r e n t ( i n p u t [] f l o a t 64 , w i n d o w _ size , num _ g o r o u t i n e s int ) [] f l o a t 64 {

2 var o u t p u t = m a k e ([] f l o a t 64 , w i n d o w _ size -1 , len ( i n p u t ) )

3 if len ( i n p u t ) > 0 {

4 num _ i t e m s := len ( i n p u t ) - ( w i n d o w _ s i z e - 1)

5 var b a r r i e r _ wg s y n c . W a i t G r o u p

6 n := num _ i t e m s / num _ g o r o u t i n e s

7 go _ max := m a k e ( [ ] [ ] f l o a t 64 , num _ g o r o u t i n e s )

8 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

9 go _ max [ i ] = m a k e ([] f l o a t 64 , 0 , num _ g o r o u t i n e s )

10 }

11 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

12 b a r r i e r _ wg . Add (1)

13 go f u n c ( go _ id int ) {

14 d e f e r b a r r i e r _ wg . D o n e ()

15

16 // c o m p u t i n g b o u n d a r i e s

17 var start , s t o p int

18 s t a r t = go _ id * int ( n ) + ( w i n d o w _ s i z e - 1) //

s t a r t i n g i n d e x

19 // e n d i n g i n d e x

20 if go _ id != ( num _ g o r o u t i n e s - 1) {

21 s t o p = s t a r t + n // E n d i n g i n d e x

22 } e l s e {

23 s t o p = num _ i t e m s + ( w i n d o w _ s i z e - 1) //

E n d i n g i n d e x

24 }

25

26 loc _ max := m a k e ([] f l o a t 64 , stop - s t a r t )

27 idx := 0

28 for i := s t a r t ; i < s t o p ; i ++ {

29 loc _ max [ idx ] = max _ in _ s l i c e ( i n p u t [ i -( w i n d o w _ size -1) : i + 1 ] )

30 idx ++

31 }

32 go _ max [ go _ id ] = a p p e n d ( go _ max [ go _ id ] , loc _ max . . . )

33

34 }( i )

35 }

36 b a r r i e r _ wg . W a i t ()

37

38 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

39 o u t p u t = a p p e n d ( output , go _ max [ i ] . . . )

40 }

41

42 } e l s e { // e m p t y i n p u t

43 fmt . P r i n t l n (" r o l l i n g _ max is p a n i c k i n g !")

44 p a n i c ( fmt . S p r i n t f ("%v", input))

45 }

46 r e t u r n o u t p u t

47 }

Listing A.13: Concurrent rolling max embracing false sharing

1 f u n c r o l l i n g _ max _ c o n c u r r e n t 2( i n p u t [] f l o a t 64 , w i n d o w _ size , num _ g o r o u t i n e s int ) [] f l o a t 64 {

2 var o u t p u t = m a k e ([] f l o a t 64 , len ( i n p u t ) )

3 if len ( i n p u t ) > 0 {

4 num _ i t e m s := len ( i n p u t ) - ( w i n d o w _ s i z e - 1)

5 var b a r r i e r _ wg s y n c . W a i t G r o u p

6 n := num _ i t e m s / num _ g o r o u t i n e s

7

8 for i := 0; i < num _ g o r o u t i n e s ; i ++ {

9 b a r r i e r _ wg . Add (1)

10 go f u n c ( go _ id int ) {

11 d e f e r b a r r i e r _ wg . D o n e ()

12

13 // c o m p u t i n g b o u n d a r i e s

14 var start , s t o p int

15 s t a r t = go _ id * int ( n ) + ( w i n d o w _ s i z e - 1) //

s t a r t i n g i n d e x

16 // e n d i n g i n d e x

17 if go _ id != ( num _ g o r o u t i n e s - 1) {

18 s t o p = s t a r t + n // E n d i n g i n d e x

19 } e l s e {

20 s t o p = num _ i t e m s + ( w i n d o w _ s i z e - 1) //

E n d i n g i n d e x

21 }

22

23 for i := s t a r t ; i < s t o p ; i ++ {

24 o u t p u t [ i ] = max _ in _ s l i c e ( i n p u t [ i -( w i n d o w _ size -1) : i + 1 ] )

25 }

26 }( i )

27 }

28 b a r r i e r _ wg . W a i t ()

29

30 } e l s e { // e m p t y i n p u t

31 fmt . P r i n t l n (" r o l l i n g _ max is p a n i c k i n g !")

32 p a n i c ( fmt . S p r i n t f ("%v", input))

33 }

34 r e t u r n o u t p u t

35 }

Listing A.14: Concurrent rolling max embracing false sharing

1 f u n c c o m p u t e _ w i n d o w _ max ( input , o u t p u t [] f l o a t 64 , start , end int ) {

2 o u t p u t [ end -1] = max _ in _ s l i c e ( i n p u t [ s t a r t : end ])

3 }

4

5 f u n c r o l l i n g _ max _ c o n c u r r e n t 3( i n p u t [] f l o a t 64 , w i n d o w _ size , num _ g o r o u t i n e s int ) [] f l o a t 64 {

6 var o u t p u t = m a k e ([] f l o a t 64 , len ( i n p u t ) )

7 if len ( i n p u t ) > 0 {

8 l e n g t h := len ( i n p u t )

9 num _ i t e m s := l e n g t h - ( w i n d o w _ s i z e - 1)

10 p e n d i n g := m a k e ( c h a n * W o r k )

11 d o n e := m a k e ( c h a n * W o r k )

12

13 // l a o d p e n d i n g w i t h w o r k

14 go f u n c () {

15 for i :=( w i n d o w _ s i z e - 1) ; i < l e n g t h ; i ++ {

16 p e n d i n g < - N e w W o r k ( c o m p u t e _ w i n d o w _ max , input , output , i -( w i n d o w _ size -1) , i +1)

17 }

18 }()

19

20 // s t a r t w o r k e r s

21 for i : = 0 ; i < num _ g o r o u t i n e s ; i ++ {

22 go f u n c () {

23 W o r k e r ( pending , d o n e )

24 }()

25 }

26

27 // w a i t t i l l all w o r k is d o n e

28 for i :=( w i n d o w _ s i z e - 1) ; i < num _ i t e m s ; i ++ {

29 < - d o n e

30 }

31

32 } e l s e { // e m p t y i n p u t

33 fmt . P r i n t l n (" r o l l i n g _ max is p a n i c k i n g !")

34 p a n i c ( fmt . S p r i n t f ("%v", input))

35 }

36 r e t u r n o u t p u t

37 }

Listing A.15: Tests for checking the correctness ofrolling_max

1 / / # # # # # # # # # # # # # # # T E S T S # # # # # # # # # # # # # # #

2 f u n c T e s t S l i c e _ in _ max _ s e r i a l 2( t * t e s t i n g . T ) {

3 t e s t _ s e r i a l _ s e r i a l _ s l i c e ( t , returns , fw , sw , r o l l i n g _ max _ serial , r o l l i n g _ max _ s e r i a l 2)

4 }

5 f u n c T e s t S l i c e _ in _ max _ c o n c u r r e n t 1( t * t e s t i n g . T ) {

6 t e s t _ s e r i a l _ c o n c u r r e n t _ s l i c e ( t , returns , fw , sw , 32 , r o l l i n g _ max _ serial , r o l l i n g _ max _ c o n c u r r e n t )

7 }

8 f u n c T e s t S l i c e _ in _ max _ c o n c u r r e n t 2( t * t e s t i n g . T ) {

9 t e s t _ s e r i a l _ c o n c u r r e n t _ s l i c e ( t , returns , fw , sw , 32 , r o l l i n g _ max _ serial , r o l l i n g _ max _ c o n c u r r e n t 2)

10 }

11 f u n c T e s t S l i c e _ in _ max _ c o n c u r r e n t 3( t * t e s t i n g . T ) {

12 t e s t _ s e r i a l _ c o n c u r r e n t _ s l i c e ( t , returns , fw , sw , 32 , r o l l i n g _ max _ serial , r o l l i n g _ max _ c o n c u r r e n t 3)

13 }

14 / / # # # # # # # # # # # # # # # T E S T S end # # # # # # # # # # # # # # #

[1] Farmer, J Doyne, 2012, Economics needs to treat the economy as a com-plex system, Comcom-plexity Research Initiative for Systemic instabilities (CRISIS).

[2] Sornette, Didier, 2009, Why stock markets crash: critical events in com-plex financial systems (Princeton University Press).

[3] Sornette, Didier and Zhuli He, Statistical Agent-Based Modelling Ap-proach (SABM) Towards Complex Financial and Economic Systems, De-scription March 2017

[4] Sornette, Didier and Zhuli He, Statistical Agent-Based Model Project Progress Report August 2016

[5] Go programs versus [...]

https://benchmarksgame.alioth.debian.org retrieved April 25, 2017

[6] https://www.cadmo.ethz.ch/education/thesis/guidelines.html retrieved April 25, 2017

[7] Go Language Patterns, Semaphores

http://www.golangpatterns.info/concurrency/semaphores retrieved June 26, 2017

[8] Master Worker Pattern

https://gist.github.com/mikewadhera/1492294 retrieved September 6, 2017

[9] Object-oriented programming

https://en.wikipedia.org/wiki/Object-oriented_programming retrieved October 28, 2017

[10] Procedural programming

https://en.wikipedia.org/wiki/Procedural_programming retrieved October 28, 2017

[11] Imperative programming

https://en.wikipedia.org/wiki/Imperative_programming retrieved October 28, 2017

[12] Functional programming

https://en.wikipedia.org/wiki/Functional_programming retrieved October 28, 2017

[13] Channels

https://en.wikipedia.org/wiki/Channel_(programming) retrieved October 29, 2017

[14] Light-weight process

https://en.wikipedia.org/wiki/Light-weight_process retrieved October 29, 2017

[15] Go at Google: Language Design in the Service of Software Engineering https://talks.golang.org/2012/splash.article

retrieved October 29, 2017

[16] Google’s Go: A New Programming Language That’s Python Meets C++

https://techcrunch.com/2009/11/10/google-go-language/

retrieved October 30, 2017 [17] Profiling Go Programs

https://blog.golang.org/profiling-go-programs retrieved October 30, 2017

[18] Interpreted language

https://en.wikipedia.org/wiki/Interpreted_language retrieved October 30, 2017

[19] General Python FAQ

https://docs.python.org/3/faq/general.html#

why-was-python-created-in-the-first-place retrieved October 30, 2017

[20] Why are Python Programs often slower than the Equivalent Program Written in C or C++?

https://stackoverflow.com/questions/3033329/

why-are-python-programs-often-slower-than-the-equivalent-program-written-in-c-or

retrieved October 30, 2017

[21] Go programs versus Python 3

https://benchmarksgame.alioth.debian.org/u64q/compare.php?

lang=go&lang2=python3 retrieved October 31, 2017

[22] The Computer Language Benchmarks Game https://benchmarksgame.alioth.debian.org/

how-programs-are-measured.html retrieved October 31, 2017

[23] Is Python interpreted (like Javascript or PHP)?

https://stackoverflow.com/questions/745743/

is-python-interpreted-like-javascript-or-php retrieved October 31, 2017

[24] Profiling Go Programs

https://blog.golang.org/profiling-go-programs retrieved October 31, 2017

[25] How to write benchmarks in Go

https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go retrieved October 31, 2017

[26] Package testing

https://golang.org/pkg/testing/

retrieved October 31, 2017 [27] Multiplexer

https://en.wikipedia.org/wiki/Multiplexer retrieved November 1, 2017

[28] Effective Go, Concurrency

https://golang.org/doc/effective_go.html#concurrency retrieved November 1, 2017

[29] Concurrency is not Parallelism

https://talks.golang.org/2012/waza.slide#1 retrieved November 1, 2017

[30] Mutual Exclusion

https://en.wikipedia.org/wiki/Mutual_exclusion#cite_note-1 retrieved November 1, 2017

[31] Race Condition

https://en.wikipedia.org/wiki/Race_condition retrieved November 1, 2017

[32] Go Concurrency Patterns

https://talks.golang.org/2012/concurrency.slide#1 retrieved November 1, 2017

[33] Communicating sequential processes

https://en.wikipedia.org/wiki/Communicating_sequential_

processes

retrieved November 1, 2017

[34] Is it possible to force a go routine to be run on a specific CPU?

https://stackoverflow.com/questions/19758961/

is-it-possible-to-force-a-go-routine-to-be-run-on-a-specific-cpu retrieved November 1, 2017

[35] Master/slave (technology)

https://en.wikipedia.org/wiki/Master/slave_(technology) retrieved November 1, 2017

[36] False sharing

https://en.wikipedia.org/wiki/False_sharing retrieved November 1, 2017

[37] Go Slices: usage and internals

https://blog.golang.org/go-slices-usage-and-internals retrieved November 3, 2017

[38] S&P 500 Index

https://en.wikipedia.org/wiki/S%26P_500_Index retrieved November 4, 2017

[39] Backtesting

http://www.investopedia.com/terms/b/backtesting.asp retrieved November 4, 2017

[40] Semaphore (programming)

https://en.wikipedia.org/wiki/Semaphore_(programming) retrieved November 4, 2017