Binary file cws/cw01.pdf has changed
--- a/cws/cw01.tex Tue Nov 08 10:37:18 2016 +0000
+++ b/cws/cw01.tex Wed Nov 09 00:52:08 2016 +0000
@@ -7,11 +7,12 @@
\section*{Coursework 6 (Scala)}
This coursework is about Scala and is worth 10\%. The first and second
-part is due on 16 November at 11:00, and the second part on 23
-November at 11:00. You are asked to implement three programs about
-list processing and recursion.
+part is due on 16 November at 11:00, and the third part on 23 November
+at 11:00. You are asked to implement three programs about list
+processing and recursion. The third part is more advanced and might
+include material you have not yet heard about in the first lecture.
-\subsubsection*{Disclaimer}
+\subsection*{Disclaimer}
It should be understood that the work you submit represents
your own effort. You have not copied from anyone else. An
@@ -19,99 +20,130 @@
uploaded to KEATS, which you can freely use.\bigskip
-\subsubsection*{Part 1 (3 Marks)}
+\subsection*{Part 1 (3 Marks)}
This part is about recursion. You are asked to implement a Scala
-program that tests examples of the \emph{$3n + 1$-conjecture}. This
-conjecture can be described as follows: Start with any positive number
-$n$ greater than $0$. If $n$ is even, divide it by $2$ to obtain $n /
-2$. If $n$ is odd, multiply it by $3$ and add $1$ to obtain $3n +
-1$. Repeat this process and you will always end up with $1$. For
-example if you start with $6$, respectively $9$, you obtain the series
+program that tests examples of the \emph{$3n + 1$-conjecture}, also
+called \emph{Collatz conjecture}. This conjecture can be described as
+follows: Start with any positive number $n$ greater than $0$:
+
+\begin{itemize}
+\item If $n$ is even, divide it by $2$ to obtain $n / 2$.
+\item If $n$ is odd, multiply it by $3$ and add $1$ to obtain $3n +
+ 1$.
+\item Repeat this process and you will always end up with $1$.
+\end{itemize}
+
+\noindent
+For example if you start with $6$, respectively $9$, you obtain the
+series
\[
\begin{array}{@{}l@{\hspace{5mm}}l@{}}
-6, 3, 10, 5, 16, 8, 4, 2, 1 & \text{(=9 steps)}\\
-9, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1 & \text{(=20 steps)}\\
+6, 3, 10, 5, 16, 8, 4, 2, 1 & \text{(= 9 steps)}\\
+9, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1 & \text{(= 20 steps)}\\
\end{array}
\]
\noindent
As you can see, the numbers go up and down like a roller-coaster, but
-curiously they seem to always terminate in $1$. While it is
-relatively easy to test this conjecture with particular numbers, it is
-an interesting open problem to \emph{prove} that the conjecture is
-true for all numbers ($> 0$). Paul Erd\"o{}s, a famous mathematician
-you might have hard about, said about this conjecture: ``Mathematics
-may not be ready for such problems.'' and also offered \$500 cash
-prize for its solution. Jeffrey Lagarias, another mathematician,
-claimed that based only on known information about this problem,
-``this is an extraordinarily difficult problem, completely out of
-reach of present day mathematics.'' There is also a
-\href{https://xkcd.com/710/}{xkcd} cartoon about this
-conjecture.\medskip
+curiously they seem to always terminate in $1$. The conjecture is that
+this will \emph{always} happen for every number greater than
+0.\footnote{While it is relatively easy to test this conjecture with
+ particular numbers, it is an interesting open problem to
+ \emph{prove} that the conjecture is true for \emph{all} numbers ($>
+ 0$). Paul Erd\"o{}s, a famous mathematician you might have hard
+ about, said about this conjecture: ``Mathematics may not be ready
+ for such problems.'' and also offered a \$500 cash prize for its
+ solution. Jeffrey Lagarias, another mathematician, claimed that
+ based only on known information about this problem, ``this is an
+ extraordinarily difficult problem, completely out of reach of
+ present day mathematics.'' There is also a
+ \href{https://xkcd.com/710/}{xkcd} cartoon about this conjecture
+ (click \href{https://xkcd.com/710/}{here}). If you are able to solve
+ this conjecture, you will definitely get famous.}\bigskip
+
+\newpage
+\noindent
+\textbf{Tasks (file collatz.scala):}
+
+\begin{itemize}
+\item[(1)] You are asked to implement a recursive function that
+ calculates the number of steps needed until a series ends
+ with $1$. In case of starting with $6$, it takes $9$ steps and in
+ case of starting with $9$, it takes $20$ (see above). In order to
+ try out this function with large numbers, you should use
+ \texttt{Long} as argument type, instead of \texttt{Int}. You can
+ assume this function will be called with numbers between $1$ and
+ $1$ million. \hfill[2 Marks]
+
+\item[(2)] Write a second function that takes an upper bound as
+ argument and calculates the steps for all numbers in the range from
+ 1 upto this bound. It returns the maximum number of steps and the
+ corresponding number that needs that many steps. The first
+ component of the pair is the number of steps and the second is the
+ corresponding number. \hfill[1 Mark]
+\end{itemize}
\noindent
-\textbf{Tasks:} (1) You are asked to implement a recursive function that
-calculates the number of steps needed number until a series ends with
-$1$. In case of starting with $6$, it takes $9$ steps and in case of
-starting with $9$, it takes $20$ (see above). In order to try out this
-function with large numbers, you should use \texttt{Long} as argument
-type instead of \texttt{Int}. You can assume this function will be
-called with numbers between $1$ and $10$ million.
-
-(2) Then write a second function that takes an upper bound as argument
-and calculates the steps for all numbers in the range from 1 upto this
-bound, and returns the maximum of steps needed by a number in that
-range. This function should produce for ranges
+\textbf{Test Data:} Some test ranges are:
\begin{itemize}
-\item $1 - 10$ where $9$ takes 20 steps
-\item $1 - 100$ where $97$ takes 119 steps,
-\item $1 - 1,000$ where $871$ takes 179 steps,
-\item $1 - 10,000$ where $6,171$ takes 262 steps,
-\item $1 - 100,000$ where $77,031$ takes 351 steps,
-\item $1 - 1$ million where $837,799$ takes 525 steps, and
-\item $1 - 10$ million where $8,400,511$ takes 686 steps
-\end{itemize}
+\item 1 to 10 where $9$ takes 20 steps
+\item 1 to 100 where $97$ takes 119 steps,
+\item 1 to 1,000 where $871$ takes 179 steps,
+\item 1 to 10,000 where $6,171$ takes 262 steps,
+\item 1 to 100,000 where $77,031$ takes 351 steps,
+\item 1 to 1 million where $837,799$ takes 525 steps
+ %%\item[$\bullet$] $1 - 10$ million where $8,400,511$ takes 686 steps
+\end{itemize}\bigskip
+
-\subsubsection*{Part 2 (4 Marks)}
+\subsection*{Part 2 (4 Marks)}
This part is about list processing---it's a variant of
-Buy-low-sell-high in Scala. (1) Given a list of prices for a commodity,
-for example
+``buy-low-sell-high'' in Scala. It uses the online financial data
+service from Yahoo.\bigskip
+
+\noindent
+\textbf{Tasks (file trade.scala):}
+
+\begin{itemize}
+\item[(1)] Given a list of prices for a commodity, for example
\[
\texttt{List(28.0, 18.0, 20.0, 26.0, 24.0)}
\]
\noindent
-you need to write a function that returns a pair for when to buy and
-when to sell this commodity. In the example above it should return
-$\texttt{(1, 3)}$ because at index $1$ the price is lowest and then at
-index $3$ the price is highest. Note the prices are given as lists of
-\texttt{Float}s.
+you need to write a function that returns a pair of indices for when
+to buy and when to sell this commodity. In the example above it should
+return the pair $\texttt{(1, 3)}$ because at index $1$ the price is lowest and
+then at index $3$ the price is highest. Note the prices are given as
+lists of \texttt{Float}s. \hfill[1 Mark]
-(2) Write a function that requests a comma-separated value list from a
-Yahoo websevice that provides historical data for stock indices. For
-example if you query the URL
+\item[(2)] Write a function that requests a comma-separated value (CSV) list
+ from the Yahoo websevice that provides historical data for stock
+ indices. For example if you query the URL
\begin{center}
\url{http://ichart.yahoo.com/table.csv?s=GOOG}
\end{center}
\noindent where \texttt{GOOG} stands for Google's stock market symbol
-then you will receive a comma-separated value list of the daily stock
-prices since Google was floated. You can also try this with other
-strock market symbols, for instance AAPL, MSFT, IBM, FB, YHOO, AMZN,
-BIDU and so on. This function should return a List of strings, where
-each string is one line in this comma-separated value list
-(representing one days data). Note that Yahoo generates its answer
-such that the newest data is at the front of this list, and the oldest
-data is at the end.
+then you will receive a CSV-list of the daily stock prices since
+Google was listed. You can also try this with other strock market
+symbols, for instance AAPL, MSFT, IBM, FB, YHOO, AMZN, BIDU and so
+on.
-(3) As you can see, the financial data from Yahoo is organised in 7 columns,
+This function should return a List of strings, where each string
+is one line in this CVS-list (representing one day's
+data). Note that Yahoo generates its answer such that the newest data
+is at the front of this list, and the oldest data is at the end.
+\hfill[1 Mark]
+
+\item[(3)] As you can see, the financial data from Yahoo is organised in 7 columns,
for example
{\small\begin{verbatim}
@@ -127,30 +159,159 @@
Write a function that ignores the first line (the header) and then
extracts from each line the date (first column) and the Adjusted Close
price (last column). The Adjusted Close price should be converted into
-a float. So the result of this function is a list of pairs where the
-first components are strings (the dates) and the second are floats
-(the adjusted close prices).
+a \texttt{Double}. So the result of this function is a list of pairs where the
+first components are strings (the dates) and the second are doubles
+(the adjusted close prices).\newline\mbox{}\hfill\mbox{[1 Mark]}
-(4) Write a function that takes a stock market symbol as argument (you
-can assume it is a valid one, like GOOG, AAPL, MSFT, IBM, FB, YHOO,
-AMZN, BIDU). The function calculates the dates when you should have
-bought Google shares (lowest price) and when you should have sold them
-(highest price).\medskip
+\item[(4)] Write a function that takes a stock market symbol as
+ argument (you can assume it is a valid one, like GOOG or AAPL). The
+ function calculates the \underline{dates} when you should have
+ bought the corresponding shares (lowest price) and when you should
+ have sold them (highest price).\hfill\mbox{[1 Mark]}
+\end{itemize}
\noindent
\textbf{Test Data:}
In case of Google, the financial data records 3077 entries starting
from 2004-08-19 until 2016-11-04 (which is the last entry on the day
-when I prepared the course work...on 6 November; remember stock
+when I prepared the course work...namely on 6 November; remember stock
markets are typically closed on weekends and no financial data is
produced then; also I did not count the header line). The lowest
-for Goole was on 2004-09-03 with \$49.95513 per share and the
-highest on 2016-10-24 with \$813.109985 per share.
+shareprice for Google was on 2004-09-03 with \$49.95513 per share and the
+highest on 2016-10-24 with \$813.109985 per share.\bigskip
+
+\subsection*{Advanced Part 3 (3 Marks)}
+
+A purely fictional character named Mr T.~Drump inherited in 1978
+approximately 200 Million Dollar from his father. Mr Drump prides
+himself to be a brilliant bussiness man because nowadays it is
+estimated he is 3 Billon Dollar worth (one is not sure, of course,
+because Mr Drump refuses to make his tax records public).
+
+The question about Mr Drump's bussiness acumen remains. So let's do a
+quick back-of-the-envelope calculation in Scala whether his claim has
+any merit. Let's suppose we are given \$100 in 1978 and we follow a
+really dump investment strategy, namely:
+
+\begin{itemize}
+\item We blindly choose a portfolio of stocks, say some Blue-Chips stocks
+ or some Real Estate stocks.
+\item If some of the stocks in our portfolio are traded in January of
+ a year, we invest our money to equal amounts in each of these
+ stocks. For example if we have \$100 and there are four stocks that
+ are traded in our portfolio, we buy in January \$25 worth of stocks
+ from each.
+\item Next year in January, we look how our stocks did, liquidate
+ everything, and re-invest our (hopefully) increased money in again
+ the stocks from our portfolio (there might be more stocks available,
+ if companies from our portfolio got listed in that year, or less if
+ some companies went bust or de-listed).
+\item We do this for 38 years until January 2016 and check what would
+ have become out of our \$100.
+\end{itemize}\medskip
+\noindent
+\textbf{Tasks (file drump.scala):}
+
+\begin{itemize}
+\item[(1.a)] Write a function that queries the Yahoo financial data
+ service and obtains the first trade (adjusted close price) of a
+ stock symbol and a year. A problem is that normally a stock exchange
+ is not open on 1st of January, but depending a the day of the week
+ on a later day (maybe 3rd or 4th). The easiest way to solve this
+ problem is to obtain the whole January data for a stock symbol as
+ CSV-list and then select the earliest entry in this list. For this
+ you can specify a date range with the Yahoo service. For example if
+ you want to obtain all January data for Google in 2000, you can form
+ the query:\mbox{}\\[-8mm]
+
+ \begin{center}\small
+ \mbox{\url{http://ichart.yahoo.com/table.csv?s=GOOG&a=0&b=1&c=2000&d=1&e=1&f=2000}}
+ \end{center}
+
+ For other companies and years, you need to change the stock symbol
+ (\texttt{GOOG}) and the year \texttt{2000} (in the \texttt{c} and
+ \texttt{f} argument of the query). Such a request might fail, if the
+ company does not exist during this period. For example, if you query
+ for Google in January of 1980, then clearly Google did not exists yet.
+ Therefore you need to return a trade price as
+ \texttt{Option[Double]}.
+
+\item[(1.b)] Write a function that takes a portfolio (a List of stock symbols),
+ a years range and gets all the first trading prices for a year. You should
+ organise this as a list of lists of \texttt{Option[Double]}. The inner lists
+ are for all stock symbols from the portfolio and the outer list for the years.
+ For example for Google and Apple in years 2010 (first line), 2011
+ (second line) and 2012 (third line) you obtain:
+\begin{verbatim}
+ List(List(Some(313.062468), Some(27.847252)),
+ List(Some(301.873641), Some(42.884065)),
+ List(Some(332.373186), Some(53.509768)))
+\end{verbatim}\hfill[1 Mark]
+
+\item[(2.a)] Write a function that calculates the \emph{change factor} (delta)
+ for how a stock price has changed from one year to the next. This is
+ only well-defined, if the corresponding company has been traded in both
+ years. In this case you can calculate
-\subsubsection*{Part 3 (3 Marks)}
+ \[
+ \frac{price_{new} - price_{old}}{price_{old}}
+ \]
+
+
+\item[(2.b)] Write a function that calculates all change factors
+ (deltas) for the prices we obtained under Task 1. For the running
+ example of Google and Apple for the years 2010 to 2012 gives
+ the 4 change factors:
+
+\begin{verbatim}
+ List(List(Some(-0.03573991820699504), Some(0.5399747522663995))
+ List(Some(0.10103414428290529), Some(0.24777742035415723)))
+\end{verbatim}
+
+ That is Google did a bit badly in 2010, while Apple did very well.
+ Both did OK in 2011.\hfill\mbox{[1 Mark]}
+
+\item[(3.a)] Write a function that calculates the ``yield'', or
+ balance, for one year for our portfolio. This function takes the
+ change factors, the starting balance and the year as arguments. If
+ no company from our portfolio existed in that year, the balance is
+ unchanged. Otherwise we invest in each existing company an equal
+ amount of our balance. Using the change factors computed under Task
+ 2, calculate the new balance. Say we had \$100 in 2010, we would have
+ received in our running example
+ \begin{verbatim}
+ $50 * -0.03573991820699504 + $50 * 0.5399747522663995
+ = $25.211741702970222
+ \end{verbatim}
+
+ as profit for that year, and our new balance for 2011 is \$125 when
+ converted to a \texttt{Long}.
+
+\item[(3.b)] Write a function that calculates the overall balance
+ for a range of years where each year the yearly profit is compounded to
+ the new balances and then re-invested into our portfolio.\mbox{}\hfill\mbox{[1 Mark]}
+\end{itemize}\medskip
+
+\noindent
+\textbf{Test Data:} File \texttt{drumb.scala} contains two portfolios
+collected from the S\&P 500, one for blue-chip companies, including
+Facebook, Amazon and Baidu; and another for listed real-estate companies, whose
+names I have never heard of. Following the dumb investment strategy
+from 1978 until 2016 would have turned a starting balance of \$100
+into \$23,794 for real estate and a whopping \$524,609 for blue chips.\medskip
+
+\noindent
+\textbf{Moral:} Reflecting on our assumptions, we are overestimating
+our yield in many ways: first, who can know in 1978 about what will
+turn out to be a blue chip company. Also, since the portfolios are
+chosen from the current S\&P 500, they do not include the myriad
+of companies that went bust or were de-listed over the years.
+So where does this leave our fictional character Mr T.~Drump? Well, given
+his inheritance, a really dumb investment strategy would have done
+equally well, if not much better.
\end{document}
%%% Local Variables:
--- a/progs/collatz.scala Tue Nov 08 10:37:18 2016 +0000
+++ b/progs/collatz.scala Wed Nov 09 00:52:08 2016 +0000
@@ -9,15 +9,18 @@
// performs the recursion. The function should expect
// arguments in the range of 1 to 10 Million.
-def collatz(n: Long): Int = ...
+def collatz(n: Long): ... = ...
//(2) Complete the collatz bound function below. It should
// calculuate how many steps are needed for each number
-// from 1 upto a bound and return the maximum number of
+// from 1 upto a bound and returns the maximum number of
+// steps and the corresponding number that needs that many
// steps. You should expect bounds in the range of 1
-// upto 10 million.
+// upto 1 million. The first component of the pair is
+// the maximum number of steps and the second is the
+// corresponding number.
-def collatz_max(bnd: Int): Int = ...
+def collatz_max(bnd: Int): (Int, Int) = ...
--- a/progs/collatz_sol.scala Tue Nov 08 10:37:18 2016 +0000
+++ b/progs/collatz_sol.scala Wed Nov 09 00:52:08 2016 +0000
@@ -24,19 +24,25 @@
//(2) Complete the collatz bound function below. It should
// calculuate how many steps are needed for each number
// from 1 upto a bound and return the maximum number of
+// steps and the corresponding number that needs that many
// steps. You should expect bounds in the range of 1
-// upto 10 million.
+// upto 1 million.
-def collatz_max(bnd: Int): Int = {
- (for (i <- 1 to bnd) yield collatz(i).length).max
+def collatz_max(bnd: Int): (Int, Int) = {
+ val all = for (i <- (1 to bnd).toList) yield collatz(i).length
+ val max = all.max
+ (all.indexOf(max) + 1, max)
}
// some testing harness
-val bnds = List(10, 100, 1000, 10000, 100000, 1000000, 10000000)
+val bnds = List(10, 100, 1000, 10000, 100000, 1000000)
for (bnd <- bnds) {
- val max = collatz_max(bnd)
- println(s"In the range of 1 - ${bnd} the maximum steps are ${max}")
+ val (max, steps) = collatz_max(bnd)
+ println(s"In the range of 1 - ${bnd} the number ${max} needs the maximum steps of ${steps}")
}
+
+//val all = for (i <- (1 to 100000).toList) yield collatz1(i)
+//println(all.sorted.reverse.take(10))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/drumb.scala Wed Nov 09 00:52:08 2016 +0000
@@ -0,0 +1,74 @@
+// Advanvced Part 3 about Mr T. Drumb investing into stocks
+//==========================================================
+
+//two test portfolios
+
+val blchip_portfolio = List("GOOG", "AAPL", "MSFT", "IBM", "FB", "YHOO", "AMZN", "BIDU")
+val rstate_portfolio = List("PLD", "PSA", "AMT", "AIV", "AVB", "BXP", "CBG", "CCI",
+ "DLR", "EQIX", "EQR", "ESS", "EXR", "FRT", "GGP", "HCP")
+
+
+import io.Source
+import scala.util._
+
+def get_yahoo_page(url: String): Option[List[String]] = {
+ Try(Some(Source.fromURL(url)("ISO-8859-1").getLines.toList)).
+ getOrElse { None }
+}
+
+def get_first_price(symbol: String, year: Int): Option[Double] = {
+ //println(s"download..${symbol} at ${year}")
+ val year_string = year.toString
+ val date_string = s"&a=0&b=1&c=${year_string}&d=1&e=1&f=${year_string}"
+ val url = """http://ichart.yahoo.com/table.csv?s=""" + symbol + date_string
+ val data = get_yahoo_page(url)
+ data.map(_.last.split(",").toList(6).toDouble)
+}
+
+def get_prices(portfolio: List[String], years: Range): List[List[Option[Double]]] =
+ for (year <- years.toList) yield
+ for (symbol <- portfolio) yield get_first_price(symbol, year)
+
+get_prices(List("GOOG", "AAPL"), 2010 to 2012)
+
+
+def get_delta(price_old: Option[Double], price_new: Option[Double]): Option[Double] = {
+ (price_old, price_new) match {
+ case (Some(x), Some(y)) => Some((y - x) / x)
+ case _ => None
+ }
+}
+
+def get_deltas(data: List[List[Option[Double]]]): List[List[Option[Double]]] =
+ for (i <- (0 until (data.length - 1)).toList) yield
+ for (j <- (0 until (data(0).length)).toList) yield get_delta(data(i)(j), data(i + 1)(j))
+
+def yearly_yield(data: List[List[Option[Double]]], balance: Long, year: Int): Long = {
+ val somes = data(year).flatten
+ val somes_length = somes.length
+ if (somes_length == 0) balance
+ else {
+ val portion: Double = balance / somes_length
+ balance + (for (x <- somes) yield (x * portion)).sum.toLong
+ }
+}
+
+def compound_yield(data: List[List[Option[Double]]], balance: Long, year: Int): Long = {
+ if (year >= data.length) balance else {
+ val new_balance = yearly_yield(data, balance, year)
+ compound_yield(data, new_balance, year + 1)
+ }
+}
+
+val p = get_prices(List("GOOG", "AAPL"), 2010 to 2012)
+val d = get_deltas(p)
+yearly_yield(d, 100, 0)
+
+def investment(portfolio: List[String], years: Range, start_balance: Long): Long = {
+ compound_yield(get_deltas(get_prices(portfolio, years)), start_balance, 0)
+}
+
+
+println("Real data: " + investment(rstate_portfolio, 1978 to 2016, 100))
+println("Blue data: " + investment(blchip_portfolio, 1978 to 2016, 100))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/drumb_sol.scala Wed Nov 09 00:52:08 2016 +0000
@@ -0,0 +1,74 @@
+// Advanvced Part 3 about Mr T. Drumb investing into stocks
+//==========================================================
+
+//two test portfolios
+
+val blchip_portfolio = List("GOOG", "AAPL", "MSFT", "IBM", "FB", "YHOO", "AMZN", "BIDU")
+val rstate_portfolio = List("PLD", "PSA", "AMT", "AIV", "AVB", "BXP", "CBG", "CCI",
+ "DLR", "EQIX", "EQR", "ESS", "EXR", "FRT", "GGP", "HCP")
+
+
+import io.Source
+import scala.util._
+
+def get_yahoo_page(url: String): Option[List[String]] = {
+ Try(Some(Source.fromURL(url)("ISO-8859-1").getLines.toList)).
+ getOrElse { None }
+}
+
+def get_first_price(symbol: String, year: Int): Option[Double] = {
+ //println(s"download..${symbol} at ${year}")
+ val year_string = year.toString
+ val date_string = s"&a=0&b=1&c=${year_string}&d=1&e=1&f=${year_string}"
+ val url = """http://ichart.yahoo.com/table.csv?s=""" + symbol + date_string
+ val data = get_yahoo_page(url)
+ data.map(_.last.split(",").toList(6).toDouble)
+}
+
+def get_prices(portfolio: List[String], years: Range): List[List[Option[Double]]] =
+ for (year <- years.toList) yield
+ for (symbol <- portfolio) yield get_first_price(symbol, year)
+
+get_prices(List("GOOG", "AAPL"), 2010 to 2012)
+
+
+def get_delta(price_old: Option[Double], price_new: Option[Double]): Option[Double] = {
+ (price_old, price_new) match {
+ case (Some(x), Some(y)) => Some((y - x) / x)
+ case _ => None
+ }
+}
+
+def get_deltas(data: List[List[Option[Double]]]): List[List[Option[Double]]] =
+ for (i <- (0 until (data.length - 1)).toList) yield
+ for (j <- (0 until (data(0).length)).toList) yield get_delta(data(i)(j), data(i + 1)(j))
+
+def yearly_yield(data: List[List[Option[Double]]], balance: Long, year: Int): Long = {
+ val somes = data(year).flatten
+ val somes_length = somes.length
+ if (somes_length == 0) balance
+ else {
+ val portion: Double = balance / somes_length
+ balance + (for (x <- somes) yield (x * portion)).sum.toLong
+ }
+}
+
+def compound_yield(data: List[List[Option[Double]]], balance: Long, year: Int): Long = {
+ if (year >= data.length) balance else {
+ val new_balance = yearly_yield(data, balance, year)
+ compound_yield(data, new_balance, year + 1)
+ }
+}
+
+val p = get_prices(List("GOOG", "AAPL"), 2010 to 2012)
+val d = get_deltas(p)
+yearly_yield(d, 100, 0)
+
+def investment(portfolio: List[String], years: Range, start_balance: Long): Long = {
+ compound_yield(get_deltas(get_prices(portfolio, years)), start_balance, 0)
+}
+
+
+println("Real data: " + investment(rstate_portfolio, 1978 to 2016, 100))
+println("Blue data: " + investment(blchip_portfolio, 1978 to 2016, 100))
+
--- a/progs/lecture1.scala Tue Nov 08 10:37:18 2016 +0000
+++ b/progs/lecture1.scala Wed Nov 09 00:52:08 2016 +0000
@@ -2,8 +2,9 @@
// webpages
-//**Assignment (values)**
-//=======================
+//**Assignments (values)**
+//(variable names should be lower case)
+//=====================================
val x = 42
val y = 3 + 4
@@ -18,6 +19,10 @@
(1 until 10).toList
+// an element in a list
+List(1,2,3,1)(0)
+List(1,2,3,1)(3)
+
//**Printing/Strings**
//====================
--- a/progs/trade.scala Tue Nov 08 10:37:18 2016 +0000
+++ b/progs/trade.scala Wed Nov 09 00:52:08 2016 +0000
@@ -1,67 +1,56 @@
-// Part 2
-
-// (1) the function that calculuates the indices
-// for when to buy the commodity and when to sell
-def trade_times(xs: List[Double]): (Int, Int) = {
- val low = xs.min
- val low_index = xs.indexOf(low)
- val rest = xs.drop(low_index)
- val high = rest.max
- val high_index = rest.indexOf(high)
- (low_index, low_index + high_index)
-}
+// Part 2 about Buy-Low-Sell-High using Yahoo Financial Data
+//===========================================================
-val prices = List(28.0, 18.0, 20.0, 26.0, 24.0)
+// (1) Complete the function that is given a list of floats
+// and calculuates the indices for when to buy the commodity
+// and when to sell
-trade_times(prices)
-assert(trade_times(prices) == (1, 3), "the first test fails")
+def trade_times(xs: List[Double]): (Int, Int) = ...
+
+
+// an example
+//val prices = List(28.0, 18.0, 20.0, 26.0, 24.0)
+//assert(trade_times(prices) == (1, 3), "the trade_times test fails")
-import io.Source
-import scala.util._
+// (2) Complete the ``get webpage'' function that takes a
+// a stock symbol as argument and queries the Yahoo server
+// at
+// http://ichart.yahoo.com/table.csv?s=<<insert stock symbol>>
+//
+// This servive returns a CSV-list that needs to be separated into
+// a list of strings.
-// (2) the function that queries the Yahoo financial data
-// servive and returns a comma-separated-value list
-def get_page(url: String): List[String] = {
- Try(Source.fromURL(url)("ISO-8859-1").getLines.toList).
- getOrElse { println(s" Problem with: $url"); List() }
-}
+def get_page(symbol: String): List[String] = ...
-// (3) the function that processes the comma-separated-value list
-// extracting the dates and anjusted close prices
-def process_page(url: String): List[(String, Double)] = {
- get_page(url).drop(1).map(_.split(",").toList).map((xs) => (xs(0), xs(6).toDouble))
-}
+// (3) Complete the function that processes the CSV list
+// extracting the dates and anjusted close prices. The
+// prices need to be transformed into Doubles.
+
+def process_page(symbol: String): List[(String, Double)] = ...
+
-// (4) the function that generates the query for a stock
-// market symbol and returns the dates for when to buy and
-// sell
-def query_comp(name: String): (String, String) = {
- val list = process_page("""http://ichart.yahoo.com/table.csv?s=""" + name).reverse
- val (tbuy, tsell) = trade_times(list.map(_._2))
- (list(tbuy)._1, list(tsell)._1)
-}
+// (4) Complete the query_company function that obtains the
+// processed CSV-list for a stock symbol. It should return
+// the dates for when to buy and sell the stocks of that company.
+
+def query_company(symbol: String): (String, String) =
+
+
+
+// some test cases
//query_comp("GOOG")
-
+// some more test cases
+/*
val indices = List("GOOG", "AAPL", "MSFT", "IBM", "FB", "YHOO", "AMZN", "BIDU")
for (name <- indices) {
val times = query_comp(name)
println(s"Buy ${name} on ${times._1} and sell on ${times._2}")
}
-
-
-
-/*
-scala trade.scala 2> /dev/null || echo "command1 borked it"
-
-command1
-if [ $? -ne 0 ]; then
- echo "command1 borked it"
-fi
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/trade_sol.scala Wed Nov 09 00:52:08 2016 +0000
@@ -0,0 +1,79 @@
+// Part 2 about Buy-Low-Sell-High using Yahoo Financial Data
+//===========================================================
+
+
+// (1) Complete the function that is given a list of floats
+// and calculuates the indices for when to buy the commodity
+// and when to sell
+
+def trade_times(xs: List[Double]): (Int, Int) = {
+ val low = xs.min
+ val low_index = xs.indexOf(low)
+ val rest = xs.drop(low_index)
+ val high = rest.max
+ val high_index = rest.indexOf(high)
+ (low_index, low_index + high_index)
+}
+
+val prices = List(28.0, 18.0, 20.0, 26.0, 24.0)
+assert(trade_times(prices) == (1, 3), "the trade_times test fails")
+
+
+// (2) Complete the ``get webpage'' function that takes a
+// a stock symbol as argument and queries the Yahoo server
+// at
+// http://ichart.yahoo.com/table.csv?s=<<insert stock symbol>>
+//
+// This servive returns a CSV-list that needs to be separated into
+// a list of strings.
+
+import io.Source
+import scala.util._
+
+def get_yahoo_page(symbol: String): List[String] = {
+ val url = """http://ichart.yahoo.com/table.csv?s=""" + symbol
+ Try(Source.fromURL(url)("ISO-8859-1").getLines.toList).
+ getOrElse { println(s" Problem with: $url"); List() }
+}
+
+// (3) Complete the function that processes the CSV list
+// extracting the dates and anjusted close prices. The
+// prices need to be transformed into Doubles.
+
+def process_page(symbol: String): List[(String, Double)] = {
+ get_yahoo_page(symbol).drop(1).map(_.split(",").toList).map((xs) => (xs(0), xs(6).toDouble))
+}
+
+
+// (4) Complete the query_company function that obtains the
+// processed CSV-list for a stock symbol. It should return
+// the dates for when to buy and sell the stocks of that company.
+
+def query_company(symbol: String): (String, String) = {
+ val list = process_page(symbol).reverse
+ val (tbuy, tsell) = trade_times(list.map(_._2))
+ (list(tbuy)._1, list(tsell)._1)
+}
+
+//query_company("GOOG")
+
+
+val indices = List("GOOG", "AAPL", "MSFT", "IBM", "FB", "YHOO", "AMZN", "BIDU")
+
+for (name <- indices) {
+ val times = query_company(name)
+ println(s"Buy ${name} on ${times._1} and sell on ${times._2}")
+}
+
+
+
+/*
+scala trade.scala 2> /dev/null || echo "command1 borked it"
+
+command1
+if [ $? -ne 0 ]; then
+ echo "command1 borked it"
+fi
+*/
+
+