Group Abstract Group Abstract

Message Boards Message Boards

1
|
8.6K Views
|
9 Replies
|
7 Total Likes
View groups...
Share
Share this post:

[?] Choose dates dynamically with a Slider?

Posted 8 years ago

I would like to select a date from a list of dates using a slider, and show the chosen date right underneath the slider in the form of a date string.. Take for instance the following simple list:

list={{2000, 1, 3}, {2000, 1, 4}, {2000, 1, 5}, {2000, 1, 6}, {2000, 1, 7}, {2000, 1, 10}, {2000, 1, 11}, {2000, 1, 12}, {2000, 1, 13}, {2000, 1, 14}}

So I could for instance choose with the slider the third element of this list, which is {2000, 1,5}, and then convert this with the command DateString[DatObject[{2000, 1, 7}]] to the data string "Wed 5 Jan 2000". Now I want this date string shown underneath the slider instead of the usual number, which in this case would be 3.

The slider would be for instance:

Slider[Dynamic[m],{1,10,1}

The problem is now that Dynamic[m] is not accepted by Part. With the command

list[[Dynamic[m]]]

one gets an error message that the result from the slider cannot be used as a part specification. How do I solve this problem? Thanks in advance for your help.

POSTED BY: Laurens Wachters
9 Replies

Laurens,

Put the Dynamic on the outside of the list, not in the part specification:

Dynamic[list[[m]]]

Putting it together you get:

Column[{Slider[Dynamic[m], {1, 10, 1}], 
  Dynamic[DateString[DateObject[list[[m]]]]]}]

Regards,

Neil

POSTED BY: Neil Singer

Laurens,

You made many good improvements! Once you work everything out you may want to open it in its own window (although in a CDF I am not sure what that would do)

Your problem is that you are not correctly handling all of your states when you change stock names.

Your code is

InputField[Dynamic[p1, {Automatic, listfun1}], String, FieldSize -> 4]

This will run listfun1 and change the stock name (although your syntax is a bit dangerous and confusing here -- I would use listfun1[#]& and make listfun1 and listfun2 functions of one variable -- although it does work the way it is)

The problem is that this code updates the value of the list1 variable, however, it does nothing to all the other variables that depend on list1 (listt, start, end, y). I recommend that you make your listfun1 and listfun2 functions update all of the variables that you need and everything will update properly when you tab out of the field. Also, you may want to add Selectable->False to your textcells so that you can't edit them and can tab over them (they will select as a whole but you can't click on them or go inside). Here is a quick hack that "fixes" list1fun but not list2fun -- I did not verify that all settings are updating properly but this should give you the general idea -- when you change something you must change everything that depends on it in a consistent way. I tried to make minimal changes although you may want to consider some reorganization that will simplify the code. For example, testing for strings in y[[1]] is not the cleanest code -- maybe consider returning just 1,2, or 3 and create some other variable with your strings and plots -- but you have to think this through to see if it causes other issues.

DynamicModule[{a, b, c, d, p1 = "GE", p2 = "MSFT", list1, list2, 
  listfun1, listfun2, listt, start, end, relprice, x, 
  y = {" price of stock 1 ", {}}, xpart, ypart, imagesize}, 
 listfun1[a_] := 
  Module[{}, list1 = FinancialData[a, "OHLCV", {2016, 1, 1}]; 
   listt = list1[[All, 1]]; 
   y[[2]] = 
    Switch[y[[1]], " price of stock 1 ", list1[[All, 2, 4]], 
     " price of stock 2", list2[[All, 2, 4]], 
     "quotient stock prices 1 and 2", 
     list1[[All, 2, 4]]/list2[[All, 2, 4]]]; 
   start = Round[Length[listt]* 0.25]; 
   end = Round[Length[listt]* 0.75]];
 listfun1[p1];
 listfun2[c_, d_] := list2 = FinancialData[c, "OHLCV", {2016, 1, 1}];
 listfun2[p2, p2];
 Panel[Column[{(*Choice of the 2 stocks*)
    Row[{TextCell["                 Stock 1:  ", Selectable -> False],
       InputField[Dynamic[p1, {Automatic, listfun1[#] &}], String, 
       FieldSize -> 4], 
      TextCell["                      Compare with stock 2:  ", 
       Selectable -> False], 
      InputField[Dynamic[p2, {Automatic, listfun2}], String, 
       FieldSize -> 4]}],(*Choice of the time interval*)

    IntervalSlider[{Dynamic[start], Dynamic[end]}, {1, Length[listt], 
      1}, ImageSize -> {500, 20}, Method -> "Stop", 
     MinIntervalSize -> 1], Dynamic[start];
    Dynamic[end];
    Row[{Dynamic[DateString[DateObject[listt[[start]]]]], 
      TextCell[
       "                                                                                                                   "\
, Selectable -> False], 
      Dynamic[DateString[
        DateObject[
         listt[[end]]]]]}],(*Choice of quantities to be plotted*)
    Row[{TextCell["      ", Selectable -> False], 
      Dynamic[RadioButton[
        Dynamic[y], {" price of stock 1 ", list1[[All, 2, 4]]}]], 
      TextCell[" price stock 1 ", Selectable -> False], 
      Dynamic[RadioButton[
        Dynamic[y], {" price of stock 2", list2[[All, 2, 4]]}]], 
      TextCell[" price stock 2 ", Selectable -> False], 
      Dynamic[RadioButton[
        Dynamic[y], {"quotient stock prices 1 and 2", 
         list1[[All, 2, 4]]/list2[[All, 2, 4]]}]], 
      TextCell[" quotient stock prices 1 and 2", 
       Selectable -> False]}], xpart = Dynamic[Range[start, end]];
    ypart = Dynamic[y[[2]][[start ;; end]]];
    Dynamic[
     ListLinePlot[
      Partition[Riffle[Range[start, end], y[[2]][[start ;; end]]], 2],
       ImageSize -> 700]]}]]]

I hope this helps.

Regards,

Neil

POSTED BY: Neil Singer

Thanks a lot for your advice. I have learnt a bit on Dynamic by now. But I am now stuck with Dynamic applied on FinancialData. I have made the following small program that should become a part of a cdf for analyzing the course of stock prices in which the user would be able to switch from stock to stock

p="ge";
Column[{DynamicModule[InputField[Dynamic[p]], 
Dynamic[ListLinePlot[FinancialData[p,{2017,10,1}][[All,2]]]]}]

This program does work, but after its evaluation my PC becomes awfully slow. Why is this, and would there be a remedy for it? I have a PC with an Intel i5 processor and 8 MB memory. Mathematica and its kernel don't seem to use very much of them, according to the windows 10 task manager. Another question is why in the result the input field and the plot are shown in a row and not in a column.

POSTED BY: Laurens Wachters

Dynamic then should be an outer wrapper not the inner:

list={
    {2000,1,3},{2000,1,4},{2000,1,5},{2000,1,6},{2000,1,7},
    {2000,1,10},{2000,1,11},{2000,1,12},{2000,1,13},{2000,1,14}};

Method 1 - indexed variable

Column[{
    Slider[Dynamic[m],{1,10,1}],
    Dynamic[DateString[DateObject[list[[m]]]]]}]

enter image description here

Method 2 - list of variables

Column[{
    Slider[Dynamic[m],{DateString[DateObject[#]]&/@list}],
    Dynamic[m]}]

Method 3 - localized variable

Manipulate[DateString[DateObject[m]], {m, list, Slider}]
POSTED BY: Vitaliy Kaurov

Laurens,

I can't help you with CDF reader -- I've never used it. I would talk to Wolfram Tech support and ask why it does not work in CDF but works in WMA. From the documentation it does say that CDF has some limitations -- maybe entering data is one of them??

Maybe CloudDeployment or some other approach is better? I really do not know but they should be able to help you with this. Or a Wolfram employee on this forum?

As to the posted code -- I suggest we have a call to discuss the details -- email me at "neils" at the domain in my profile and we can discuss the code.

Regards

POSTED BY: Neil Singer
Posted 8 years ago
POSTED BY: Updating Name
POSTED BY: Laurens Wachters

Laurens,

Your posted code did not have matching delimiters but I got the same behavior (once fixing it) because the FinancialData call is time consuming.

I fixed it one way (the easy way --- but more limiting) with this code by using a Manipulate.

Manipulate[
 ListLinePlot[FinancialData[p, {2017, 10, 1}][[All, 2]]], {p, "ge"}, 
 ControlType -> InputField]

You can use Dynamic directly but you must handle more details this way:

DynamicModule[{p, plotfun, plot}, p = "ge"; 
 plotfun[a_, b_] := 
  plot = ListLinePlot[FinancialData[a, {2017, 10, 1}][[All, 2]]]; 
 plotfun[p, p]; 
 Column[{InputField[Dynamic[p, {Automatic, plotfun}], String], 
   Dynamic[plot]}]]

The way this works is to make the variables p, plotfun (the function for plotting), and the plot itself local . This is so we do not mess with global variables (although you can make them global if you want). I define a function to make the plot called "plotfun" so I can call it two times -- once at initialization so we start with a default plot and once in operation. Note that I used String as the second argument to InputField so we do not need to deal with the quotation marks. I use the optional arguments to Dynamic {fstart,f,fend}. Read about these but I defined them to be {Automatic, plotfun} -- during editing the inputfield MMA automatically updates the variable "p" but at the end (when you hit tab or return) it runs the function "plotfun" (which updates our plot --- only once!!! so we do not bring the machine to its knees repeatedly getting financial data.

Regards

Neil

POSTED BY: Neil Singer
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard